Mapframe Information - pennyworth12345/A3_MMSI GitHub Wiki
This bulk of information found on this page is from myself (Pennyworth) and ianbanks, some portions of the calculations are from Miro's bLandscapeTools Blender addon. Most of the information on this page as it currently stands is with respect to having a resolution of one between your terrain size and sat/mask image, i.e. your terrain is the same size as your sat/mask.
Grid size
The dimensions of your heightmap are the same as what you'll select for the Grid size
. A heightmap defines the height of the terrain at a given X and Y coordinate. The options for Grid size
are all powers of two, this is because it's easy computationally to downscale to a lower power of two, which is done at times as an optimization. What dimensions you choose for your heightmap depends on what size you want your terrain to be and what cell size you want to use. Something to keep in mind though is that each time you go up another grid size, the number of points defined in that grid are quadrupled. For example, a 16 x 16 grid has 256 points, while a 32 x 32 grid has 1024 points.
If you're having trouble visualizing how the heightmap works, here is an example for a 16 x 16 grid (which you should never use yourself). To start, think back to your youth math classes when you first learned about graphing points on an X and Y plane. You were provided an X and Y coordinate and likely told to draw a dot at those coordinates. However, this is only a two-dimensional space. You can imagine a similar X and Y coordinate system within a heightmap, but instead of a dot at those coordinates, a numerical value is defined, which sets the height at that coordinate pair. This height value defined for a given X and Y coordinate now allows the heightmap to translate into a three-dimensional space that can be used for creating a terrain.
In the example image below consider the X axis to be horizontal, and the Y axis to be vertical. Above, below, left, and right of the square you'll find numbering for the axes. You can pick an X and Y coordinate, such as, six for your X, and two for your Y. This will give you the height of four.
Cell size
The Cell size
property designates the distance in meters (for use in-game) between two points on your heightmap. If you multiply the Grid size
by the Cell size
, you get the total terrain size. The lower the cell size, the closer together points from your heightmap are. Therefore a lower cell size allows you to have much more detailed bits of terrain. Shown below are two examples of trying to create two hills with a ditch in between them, but with two different cell sizes. For this example assume you are looking at the terrain from the side as a cross-section, and the Y-axis denotes the height of the terrain.
10 meter Cell size | 2 meter Cell size |
---|---|
![]() |
![]() |
After seeing that example you would think, "Well then why don't I use the lowest cell size I can?" Yes, you should use the lowest cell size you can, but to a limit. As you get lower and lower in cell size, there is more performance overhead. Like many things in terrain making, it's therefore important to try and strike a balance between quality and performance. For information on what cell sizes have been used by BI on their maps, see Snakeman's page about grid and cell size.
Tiling of the Satellite and Mask Images
Due to the size of the satellite and mask images, it's not efficient performance wise to keep the whole images sitting in memory while playing. Instead, the world gets broken up into tiles, which is what Terrain Builder creates when you generate layers. This means that at any given time the game only needs to show you the tiles that are in your character's view. Additionally, the tiles need to overlap to allow for seamless transitions. The number of tiles, the size of the tiles, and the overlap of those tiles are all determined from the mapframe properties you enter. For information on how those mapframe property values are calculated, see the mapframe calculations section.
Below is an example of how Terrain Builder splits a terrain into overlapping tiles. The mapframe properties of this example are the following:
Grid size: 512 x 512
Cell size (m): 4
Terrain size (m): 2048
Satellite/surf mask size (px): 2048
Resolution (m/px): 1
Texture layer size (m): 32 x 32
The image will look initially overwhelming so just focus on one color at a time, and hopefully, the following table will clear it up. The summary is that each time you go forward 512 pixels (tile size), the next tile will start 128 pixels (overlap) before where the previous tile ended.
Row/column # | Start Position (px) | End Position (px) | Size | Color | Next Start Position | Next End Position |
---|---|---|---|---|---|---|
1 | 0 | 448 | 448 | Pink | 448 - 128 = 320 | 320 + 512 = 832 |
2 | 320 | 832 | 512 | Green | 832 - 128 = 704 | 704 + 512 = 1216 |
3 | 704 | 1216 | 512 | Blue | 1216 - 128 = 1088 | 1088 + 512 = 1600 |
4 | 1088 | 1600 | 512 | Red | 1600 - 128 = 1472 | 1472 + 512 = 1984 |
5 | 1472 | 1984 | 512 | Aqua | 1984 - 128 = 1856 | 2048 (right border) |
6 | 1856 | 2048 | 192 | Gold |
You may have noticed the first and last rows/columns were of a different size. This first tile will only contain 448 pixels of the source image. This because it's offset both vertically and horizontally by 64 pixels (half of the overlap). However, technically the actual image file needs to be 512 x 512 pixels, and therefore Terrain Builder adds some stretched junk to those areas. The last tile's size is restricted by the right edge of the source image. Thus the last tile will only be Terrain size - (Previous tile end - overlap) = 2048 - (1984 - 128) = 192
. Similarly to the first tile, Terrain Builder will add the stretched edge pixels to make the actual image file 512 x 512 pixels. What that stretching looks like is shown in the table below.
First tile (first row, first column) | Last tile (last row, last column) |
---|---|
![]() |
![]() |
Stretching at edge tiles
As can be seen from this table shown previously, it's possible to encounter an issue where the last row and column of tiles have pixels stretched out to the edge of the tile. No matter what when looking at the mask tiles generated by Terrain Builder you will see some pixels stretched at the edges. The amount at which by default they'll be stretched is equal to your overlap divided by two. Firstly, we'll consider this issue to be binary, whether the last row and column edges are stretched or not. Then, we can look at how much stretching is expected.
The math to determine whether the tiles will have equal stretching around all edges of your map is fairly straight forward. You first attempt to find the size of your terrain using the known Tile size
, Actual overlap
, and Tiles in row
values.
Estimated size = (Sat and mask tile size - Actual overlap) * Tiles in row
If the estimated size is the same value as the Terrain size
you've defined in the mapframe properties then you can expect the stretching at all edges to be a consistent amount of your Actual overlap
divided by two. However, if they're not equal, more math needs to be done, which will be shown below the second example.
Example 1:
Terrain size (m): 7680
Sat/mask tile size (px): 512
Actual overlap (px): 32
Tiles in row (tile): 16
Estimated size = (Sat and mask tile size - Actual overlap) * Tiles in row = (512 - 32) * 16 = 7680
Terrain size is the same as the Estimated size
As we've seen, the estimated size and terrain size for those given mapframe properties were the same, and as stated before, the stretching of the edge tiles will be consistently equal to the Actual overlap
divided by two. What that scenario looks like is shown in the following table.
First tile (first row, first column) | Last tile (last row, last column) |
---|---|
![]() |
![]() |
Example 2:
Terrain size (m): 2048
Sat/mask tile size (px): 512
Actual overlap (px): 128
Tiles in row (tile): 6
Estimated size = (Sat and mask tile size - Actual overlap) * Tiles in row = (512 - 128) * 6 = 2304
Terrain size is not the same as the Estimated size
Now that we've seen the estimated size and terrain size didn't match, we can determine how much stretching is to be expected on the tiles in the last row and column. To figure that out, it's needed to first find how much of the source image will be shown in that tile. This can be defined as
tileSizeAfterOverlap = Tile size - Actual overlap
tileSizeAfterOverlap = 512 - 128 = 384
Last tile source width = (tileSizeAfterOverlap * Tiles in row - Terrain size) - (Actual overlap / 2)
Last tile source width = (384 * 16 - 2048) - 64 = 192
Meaning that the last tile has 192 pixels from the source image and then the remaining pixels for that 512 x 512 pixel tiles is 512 - 192 = 320
pixels. This is shown in the table below.
First tile (first row, first column) | Last tile (last row, last column) |
---|---|
![]() |
![]() |
Mapframe Properties Calculations
To start, the names in the mapframe properties window aren't very clear and to some extent wrong. However, for the sake of clarity, the labels below will match those shown in Terrain Builder. If you'd like more information on what the purpose of these properties are, then see the What do these values do? section below.
Resolution (m/px) = Terrain size / Sat and mask source image size
Terrain size (m) = Grid size * Cell size
Texture layer size options = {2⁰, 2¹, ... , 2⁸} * Cell size
Landgrid (m) = floor(Terrain size / Texture layer size)
Wanted sat grid (cells) = (Sat and mask tile size - Desired overlap) / Cell size
Final sat grid (cells) = (Sat and mask tile size - Actual overlap) / Cell size
Satellite segment (px) = (Sat and mask tile size - Actual overlap) / Texture layer size
The calculation for Tiles in row
requires first finding the Actual overlap
value, which is a multi-step process. The Desired overlap
value is the starting point of finding the overlap, and thus your Actual overlap
will never be less than the Desired overlap
. Generally speaking, the lower the overlap the better, and therefore it's important to start the Desired overlap
at a lower value, such as 16.
startTileSizePixels = Sat and mask tile size - Desired overlap
startTileSizeMeters = Resolution * startTileSizePixels
landgridCellCount = startTileSizeMeters / Texture layer size
// The number of landgrid cells must be divisible by four with no remainder
// Therefore need to subtract the remainder when dividing by four, which can be done using the modulus function
landgridCellCount -= landGridCellCount % 4
tileSizeMeters = landgridCellCount * Texture layer size
tileSizePixels = tileSizeMeters / Resolution
Actual overlap = Sat and mask tile size - tileSizePixels
// Tiles in row is rounded up because you can't have a decimal number of tiles
Tiles in row = ceil(Terrain size / tileSizeMeters)
What do the mapframe values do?
This information is more for those that are curious, rather than required knowledge.
Texture layer size
For performance optimizations, a single tile of the terrain gets further broken down into multiple pieces, also referred to as landgrids, which is what they list as the texture layer size in the mapframe properties window. The options you are given in the dropdown menu for the texture layer size is a product of your cell size. Those options are derived from multiplying the cell size by powers of two, from zero to eight, i.e.:
[1 * Cell size, 2 * Cell size, 3 * Cell size, ..., 8 * Cell size]
Landgrids have multiple important roles:
Collision
When checking for collision of objects, the game will check only the landgrid the object is currently in, and those immediately adjacent to it. This means that collision wouldn't work if an object were to span more than two landgrids. Resultingly, the max size of an object horizontally can vary from one terrain to another, since the landgrid size is dependent on the cell size of a terrain. To try and guarantee an object works on all maps, the recommendation for landgrid size (texture layer size) is as close to 40 meters as you can get. Though for extremely large terrains where your cell size is larger, this may not be possible.
Ground texture tiling
In conjunction with parameters in the RVMATs defined in your layers.cfg
, the landgrid (texture layer) size dictates how many times a surface texture will repeat within that landgrid size. This means that the texture layer size and the RVMAT parameter control the scaling of a surface texture. Here is an example from one of the Tanoa surface RVMATs:
class Stage1
{
texture = "a3\map_data_exp\gdt_vbeach_nopx.paa";
uvSource = "tex";
class uvTransform
{
aside[] = {5,0,0};
up[] = {0,5,0};
dir[] = {0,0,0};
pos[] = {0,0,0};
};
};
class Stage2
{
texture = "a3\map_data_exp\gdt_vbeach_co.paa";
uvSource = "tex";
class uvTransform
{
aside[] = {5,0,0};
up[] = {0,5,0};
dir[] = {0,0,0};
pos[] = {0,0,0};
};
};
The values to note are the aside
, and up
. The value of 5 means that in any given landgrid, if this texture were to be placed from end to end with itself, it would only occur 5 times. In other words, every Landgrid / 5
meters you'd expect to see the texture repeating itself. All of BI's surface RVMATs for Arma 3 use a value of 5. However, in Arma 2 they used a value of 10. Subsequently, the surface textures for Arma 2 and Arma 3 were designed with different scaling in mind, thus you need to be careful when mixing them. In the table below is a comparison of a texture repeating 5 times in a landgrid, and the same texture repeating 10 times in a landgrid.
Ground texture repeating 5 times per landgrid | Ground texture repeating 10 times per landgrid |
---|---|
![]() |
![]() |
Landgrid
This property should really be called something along the lines of Landgrids in row
. This value represents the width and height of the terrain, with respect to the number of landgrid cells. Within a single tile, there are (Tile size - Actual overlap) / Texture layer size
landgrid cells.
There is an example that can be found below to illustrate the subdivision of a single tile into landgrid cells. In the first image shown, the red represents a full 512 x 512 tile, while the the blue square is the area after accounting for the Actual overlap
.
This second image is showing the blue square shown previously being separated into individual landgrid cells. The black lines between the teal squares are the boundaries of that landgrid cell square.