terrain documentation¶
This file describes the research done on terrain rendering.
Contents of terrain.drs¶
27 slp files for terrain data, each slp stores one terrain type with all tiles.
id | filename | priority | tilecount | description |
---|---|---|---|---|
0 | 015000.slp | 70 | 100 tiles | brown dirty earth |
1 | 015001.slp | 102 | 100 tiles | more dry grass |
2 | 015002.slp | 139 | 100 tiles | light water |
3 | 015004.slp | 155 | 36 tiles | full grown farm field |
4 | 015005.slp | 157 | 36 tiles | decaying farm field |
5 | 015006.slp | 101 | 100 tiles | dirt with little grass |
6 | 015007.slp | 106 | 100 tiles | dry grass |
7 | 015008.slp | 90 | 100 tiles | dark grass |
8 | 015009.slp | 100 | 100 tiles | normal grass |
9 | 015010.slp | 80 | 100 tiles | desert |
10 | 015011.slp | 92 | 100 tiles | sandy dry grass |
11 | 015014.slp | 60 | 100 tiles | swamp |
12 | 015015.slp | 140 | 100 tiles | deep water |
13 | 015016.slp | 141 | 100 tiles | ocean |
14 | 015017.slp | 110 | 100 tiles | sandy sand |
15 | 015018.slp | 122 | 100 tiles | ancient building fundaments |
16 | 015019.slp | 123 | 100 tiles | dirt ancient building fundaments |
17 | 015021.slp | 150 | 9 tiles | ready and empty farm field |
18 | 015022.slp | 151 | 9 tiles | stage 0 plants on farm field |
19 | 015023.slp | 152 | 9 tiles | stage 1 plants on farm field |
20 | 015024.slp | 40 | 100 tiles | ice |
21 | 015026.slp | 130 | 100 tiles | snow |
22 | 015027.slp | 132 | 100 tiles | dirt with snow |
23 | 015028.slp | 134 | 100 tiles | grass with snow |
24 | 015029.slp | 136 | 100 tiles | grass with snow |
25 | 015030.slp | 162 | 100 tiles | ancient building fundaments with snow |
26 | 015031.slp | 120 | 100 tiles | grass ancient building fundaments |
One terrain tile is a parallelogram with equal side lengths, and the same angles in edges on opposing sides. (This is also known as a rhombus.)
Tile image height = 97px Tile image width = 49px
Half-tile structure: (#
is any pixel, @
is the center pixel for the entire tile)
#
#####
#########
#############
#################
#####################
#########################
#############################
#################################
#####################################
#########################################
#############################################
#################################################
#####################################################
#########################################################
#############################################################
#################################################################
#####################################################################
#########################################################################
#############################################################################
#################################################################################
#####################################################################################
#########################################################################################
#############################################################################################
################################################@################################################ <| 97 pixels, 25th row
Drawing smooth uniform terrain is simple:
#
is a single terrain tile.
this illustration shows the coordinate grid we use for the tile drawing.
3
2 #
1 # #
x= 0 # * #
# # # #
y= 0 # # #
1 # #
2 #
3
Tile *
is at (2, 1).
The formula for selecting the correct terrain .SLP frame index at position (x, y):
tc = sqrt(terraintilecount) #=10 for regular terrains
frame_id = (x % tc) + ((y % tc) * tc)
Terrain blending modes¶
blending mode: see the blendomatic docs for more information about terrain blending.
blending mode id correction:
stored mode | terrain type | corrected mode |
---|---|---|
0 | dirt, grass | 1 |
1 | farms | 3 |
2 | beach | 2 |
3 | water | 0 |
4 | shallows | 1 |
5 | roads | 4 |
6 | ice | 5 |
7 | snow | 6 |
8 | not assigned | 4 |
Terrain elevations¶
Drawing and blending in flat elevation.
Sloped tiles¶
generated by texture mapping the flat tiles and lighting them (in HSV color space) blend RGB space, maybe blending them in HSV space could reduce the amount of grey. lift up the vertices by half of their diamond height.
view_icm.dat¶
“inverse color map”
=> get best color_palette entry rgb to palette index transformation table with 10 variations of brightness
=> 10 color maps, 32x32x32 lookup table, 1 byte indices. => 10 32 kilobyte structures
brightness variation: use row 0..9
fetches the closest color index in the color_table for a given rgb (3 x 8 bit) value. set each “axis” (the 32 bit position) to the upper 5 bits of r, g, b (shift >> 3) select one row => coordinates in the table:
offset = i * (32^3) + r * 32^2 + g * 32 + b
i == [0,9] = icm index
palette_index = byte_at(offset)
sloped terrain lighting brightness levels 1 ICM: normal/unlit pixels (flat tiles) 9 ICMs: lighting => 4 step of darkening and 4 steps of brightening, 1 neutral. one ICM maps to the 50500 palette the other 9 adjust the pixel brightness.
generating the other ICMs: lighting in HSV color space, modify S and V separately. for each RGB value in the ICM, convert to HSV, multiply (clamped) S and V by modifiers convert the resulting HSV color back to RGB. look up this color by the standard ICM, store back palette indices for the modified light to new ICM.
lighting on sloped tiles: sloped/elevation tiles are dynamically generated by texturemapping flat tile data onto the sloped format filtermaps.dat does that texture mapping operates on the RGB values |> weighted bilinear filtering of the source pixels => to convert the resultant R G B back to a palette_index ==> ICM lookup multiple ICMs: pixel lighting step done in higher quality HSV color, no performance impact: lighting data is precalculated.
ICMs may not contain system reserved colors at the beginning and end of the palette => some colors are not used/present in the ICMs
tileedge.dat / blkedge.dat format¶
blkedge.dat
contains bitmasks that are used for drawing edges for fog of war and unexplored regions.
struct tile_edge {
uint32_t elevation_offsets[17];
struct {
uint32_t tile_offsets[94];
struct {
struct {
uint8 y; // 0 <= y <= 72
uint8 x0; // 0 <= x0 <= 96
uint8 x1; // 0 <= x1 <= 96 && x0 <= x1
} spans[n]; // repeat until y == 255
} tiles[94]; // each starting at tile_offsets[i]
} elevations[17]; // each starting at elevation_offsets[i]
}
blkedge.dat: replace 94 with 47, otherwise same format.
each ‘spans’ == pixels from (x0,y) to (x1,y) (inclusive) to set to 1; => 17*94 tiles, each 97x73 1-bit pixels
patternmasks.dat format¶
No idea what this data is for, also the format’s not verified yet. filesize = 164000 bytes = 2^5 * 5^3 * 41 bytes
164000 bytes / 16 = 10250 bytes
64 * 64 * 40 bytes = 163840 bytes, 160 bytes left then. (64 * 64 + 4) * 40 bytes = 164000 => win.
struct patternmasks {
struct {
uint_32 unknown; //4 bytes: 0x00100000 => if uint32: 1048576
char data[64*64];
} mask[40];
}