Welcome to this guide on using Landscapes in Unreal Engine. The process of getting heightmaps from WorldMachine can be full of uncertainty and mystery. This guide will dispel the confusion.
I found that there wasn’t a lot of information that I could find on how to get a map from world machine and import it into unreal engine and get a one to one result EXACTLY. I believe I have found the answer to that problem and you will find it here.
I’m going to put this link here which is the Official Documentation from Epic on the technical aspects of Landscapes
I will be quoting from this guide too where relevant.
I also did a livestream recently that covers a lot of this information which is available here….
Important fact to remember about scale
First before going into heightmaps, we shall look at the landscape system from a technical point of view and get some terminology out of the way.
The first point I want to get out of the way and should be the main thing to remember which will help down the line, is that….
If your Landscape Actor Scale is at 1,1,1, then each vertex will be 1 unreal unit apart in x & y.
The Actor Scale will eventually be the thing that controls the physical size of the landscape and hence how you control getting a 1 to 1 perfect mapping between World Machine and Unreal Units (which are 1cm per unit).
One ‘Landscape’ in the level will be an Actor that contains one or more landscape components. Together, these components act as one giant grid. Also to confuse things further each component can have sub-sections too. Think of these as ‘mini-components’ per component. It is arranged this way so that it can optimize the way that the data is organized so that we don’t have too many vertices. It also supports a Level of Detail (LOD) system that takes advantage of the way the data is organized.
The technical guide has a nice picture displaying these parts…..
Actor – Any number of components. Is a high level way of laying out the landscape data.
Component – Each component is a separate draw call and is made up of either 1 section or 2×2 sections. Where the components line up up, they ‘share’ vertices..
Section – The lowest level of data which is a number of vertices which are a power of two. Where sections line up, they also ‘share’ vertices.
Strange resolutions and Shared edges
The Landscape guide suggests some resolutions for heightmaps that at first look odd. Also importing heightmaps and using the autofit functionality will suggest odd resolutions too. The reason for this is due to the way that vertices are arranged in sections and components.
Each section will have a number of vertices which must be a power of 2 to be able to map the texture to each vertex exactly. When the sections are combined, at the edge of each section, the vertices are duplicated and overlap each other. The vertices that are at the edge read from the same pixel to get their height and when rendered, look like there is only one vertex there. We can now see where these resolutions come out. If we have a section size of 64×64, then that will equal 63 quads per section (because there are 64 vertices and the quads are the spaces in between the points). Then if we specify 2×2 sections per component, the adjacent sections will also have 63 quads and share the edge vertices. This will give 4 components with a total of 126×126 vertices due to the shared edges.
The Technical Guide has a list of common setups that give the best performance.
Landscapes are divided into multiple Components, which are Unreal’s base unit of rendering, visibility calculation, and collision. Components in a Landscape are all the same size and are always square.
Each section can be made up of a number of vertices that is a power of two, (8×8, 16×16, 32×32, 64×64, 128×128, 256×256)
Section size is mainly for performance and the ability to LOD efficiently. Please read the section on the technical guide….
Larger sizes will allow for fewer components and will be less costly on the CPU.
Components can optionally be divided into either 1 or 4 (2×2) subsections. These sections are the base unit of Landscape LOD calculation.
Then we also consider the fact that components share edges with the adjacent component in exactly the same way so that the connection between sections of separate components are seamless and behave the same way by being at the same height.
So to recap on what we have discovered so far, we have learned that a ‘Landscape’ is a single Actor that has any number of arranged square Components, each of which has 1 or 4 (2×2) sections which themselves contain vertices. The resulting resolution of the geometry will depend on how we have configured the various sizes for the sections and number of components.
We have also learned that we can have irregular arrangement of components but we will be sticking to square arrangements for now to make working with maps easier.
This guide is not a tutorial on how to use world machine. But I will talk about the things that you will want to consider for setting your World Machine project setting and exporting your maps.
So a convention seems to be to export 1 meter per pixel. This seems to be a good compromise between detail and performance. If you want to have a higher res Terrain then you will want to export a higher resolution from World Machine. I will cover the 1 meter to 1 pixel process here but will show how to set your values to get higher res results as well. I want to provide the information so that you can decide for yourself what resolution you want.
To get this 1meter to 1 pixel result, a common thing I have seen people do is just export 2048×2048 pixel heightmaps from World Machine and expect that to create a 2km terrain. It does. Roughly. If you really want to get physical distances exact, read on.
The goal here will be to export a map so that each vertex will get 1 pixel assigned to it exclusively. If we export a 2048×2048 or other power of two image then the way Unreal will assign the values to the terrain vertices will not be 1 to 1.
How to work out XY Scale and Z Height Values.
First lets deal with how we work out the width*height scale that the Unreal Landscape actor should be by looking at the component sizes. The heightmap is going to be imported and each pixel is going to be assigned to a vertex. Each vertex is going to be created at 1 unreal unit apart regardless of the section size/num components. If there aren’t enough components/sections to cover the map resolution then your landscape will clip. If there are too many, it will pad. That is one reason why there is a list of recommended sizes on the unreal site.
So once the map has been imported and applied, the landscape is default scaled by 100% so that each vertex is 1 meter apart. If you want higher density of points (but the same size) then you are going to have to create a terrain that has more components & section size and then scale ‘DOWN’ the terrain to compensate.
At scale of 50 will give two vertices per meter. A scale of 25 will give 4 vertices per meter. This is just a consequence of each vertex just explicitly being created 1 unit apart and then scaled up. The resolution of your eventual heightmap will have to match your terrain resolution so that the pixels match the vertices. Otherwise you get cropping or padding where there are enough vertices or they don’t have data.
Setting the right width scale
This is where things can get tricky. Depending on how you want to look at it, you can do things one of two ways. First, it to export your world machine heightmap at the recommended size from the Unreal list and consider that as your actual distance. So for example you can export at 2017×2017 and interpret that in your world as 2017 meters (if you have a scale of 100 on the actor). Or if you have crafted the world machine application so that you want 2 vertices per meter, then you will input a scale of 50 and that will mean that it is 1008.5 meters.
But what if you have specific distances in mind? Lets say that you want a landscape that is exactly 2000 meters. You will probably set the max extents in World Machine to 2k meters (even though it is a bit arbitrary), but then you still want to be able to export at the 2017×2017 recommended resolution because that gives the most optimal performance. So set the normal build resolution to one of the unreal recommended landscape sizes.
Here is what you do to map exact physical distances to resolution and then to exact unreal units to maintain a 1 to 1 relationship. You get your Physical Distance and then divide that by the HeightmapResolution. This gives meters divided by the number of pixels which should fit all of the pixel in that distance. This is in unreal units (cm’s) so multiply by 100 to give the correct Actor width (x & y) scale that you set directly.
Actor Width (x & y) Scale = (Physical Distance / HeightmapResolution ) * 100
- Set Max Extents in world machine to the Physical Distance that you want to work in.
- Author your landscape as you would with all of the technical artistry that you can muster.
- Set the normal build resolution to one of the recommended sizes.
- Import the heightmap onto the landscape and choose best fit. If its one of the recommended sizes, it should fit to a nice arrangement of components/sections/vertices and you shouldn’t have to worry about it anymore.
- Set the Actor scale to (Physical Distance / HeightmapResolution ) * 100
Distance is 2000 meters in world machine and this is what you want to have in unreal. Set the build resolution to 4033 (one of the recommended sizes). Import the map and auto fit. Then set the actor width scale (x & y) to (2000/4033) * 100 which is 49.59087~. This will exactly fit the 4033 vertices into the 2000 meter distance.
Of course if you wanted to approach it from the perspective of how many vertices per meter you could just import the map and have scale of values of 50, 25, 12.5, 6.25, 3.125 etc to get 2 pixels per meter (ppm), 4ppm, 8ppm, 16ppm and 32ppm respectively. But then you will have a strange physical distance of a landscape. I prefer knowing the actual size of it and prefer it being 2k or whatever. It could even be 709.7 meters with a build res of 1009×1009 (a totally arbitrary distance number but might be in your requirements) and you would still be able to fit the build res into that space by doing (709.7/1009) * 100 = actor scale of 70.336~ and it would fit exactly. Also when it comes to setting the height z scale then doing it the way I have makes getting a 1 to 1 mapping easier. Setting the width to arbitrary values breaks the relationship with the height scale and its hard to work out the right values to make it consistent.
So that pretty much covers the width and length. If you are still unsure, then try importing some maps of different sizes and see what the results are.
Landscape height scale
The height of the landscape is a slightly different numerical problem but we can approach it in a similar way. Instead of now having a number of vertices which we have to map to an x or y coordinate, we have 16-bit heightmap values which control the hight of the vertices.
One experiment we can do to see what we are working with here is to create a blank landscape that will be the same dimensions as the heightmap. Then manually paint to the extreme height/depths allowed. to find the min and max values that it can support.
The place two actors on the ridges and hit ‘End’ to snap to the ground. This will give us the exact range that the Landscape maps to. Keeping in mind that the default actor scale of a landscape is 100, the min and max height values that we get are.
Min -25500 cm (unreal units) or -255 meters
Max 25700 cm (unreal units) or 257 meters.
This is a range of 512 meters from a terrain that has a Z scale of 100%. We can say at this point that we will get this with any terrain. It is just how the Landscape system works. It is also worth pointing out that this scale range is independent from XY Scale.
Then we have the maps that we are importing. A 16 bit bit png or RAW r16 file stores the height values from 0 (black) to 65536(white). This is what 16 bit means, that there are 65536 discrete independent unique intervals that can represent the hight. Lets look at one interesting side effect from this. If we create a 256 meter constant(same flat value everywhere) heightmap with a maximum extents in world machine of 512m (which sets the upper range) then we should get a mid grey map and when applied to a landscape in unreal we should see it at level 0. It comes in at -0.781738. Oh no is something wrong?!
No actually. To illustrate what is going here, we shall look at a 2 bit image. It can store 4 discrete values. This is how binary data works. The number of things you can store is dependent on how many ways you can rearrange the bits and have a unique result. It really means that we can have a certain amount of ‘steps’ inbetween the minimum and maximum. It’s just how we interpret these bits that matter. In this case just a binary number keeps track of which ‘step’ we are at in the values that we know are between 0 and 1. Its only when we get to the highest one that we interpret that at 1.
The possible numbers of discrete steps that a binary number can give us is given by 2^n where n is the number of bits used. So in this case 2^2 where n is 2 gives us 4 bits. If we used 3 bits, we would have 2^3 values available which is 8 steps.
You can see a table of the possible numbers of steps in this wikipedia article of Powers of Two.
A standard 8 bit image (which jpgs, and most images you find) has 256 possible values. We usually have 3 channels of those as well which is why you sometimes see a 3 or 4 channeled map being referred to as 24 bit or 32 bit. It’s not that the image is storing 32 bit data in that case but rather it is 3 or 4 times 8 bits. Super confusing I know.
If we have the original landscape unscaled so that it goes from -256 cm to +256 cm then that makes the centre at 0 cm in Z with a total range of 512 cm.
If you divide 512 (our range in unreal units on an unscaled landscape actor) by 65536 (the possible range of values the map could be) then we get 0.0078125. This means that for every 16 bit value, the position that gets translated to unreal space will jump 0.0078125. Also, the 16 bit range, while it has 65536 values, because of the way computers work, these values go from 0 to 65535 (1 less than 65536). The halfway point is 65535/2 = 32767.5. This has to be a whole integer though because its a 16bit integer we are dealing with. That gets rounded down to 32767 (because the landscape displaces its geometry down). The midvalue is found from starting by considering the landscape to start at 0 in Z and end at 512 in Z and then multipliying 0.0078125 by 32767 = 255.9921875 this would be the midpoint if it was from 0 to 512. Then because we want to shift the landscape down to -256 to +256, we subtract 256. this is what gets our mid value at -0.00781~.
Then when we scale the landscape by 100 to make it into meters we get -0.781~. So thats how that happened. simples.
So the next thing is that we want to get our heightmap to transform into the right height values so that it gives the exact heigh we wanted from world machine. Again I haven’t seen any information on this anywhere else so please let me know if there are any resources you have come across.
The big thing you will first want to do it make sure that your max elevation in World Machine is close to what your actual maximum height is in the landscape. This is because you want to maximize the bit depth in the 16-bit file so that you get the optimal vertical resolution. If you have a maximum elevation of 2000 meters but the highest point in the landscape is physcally only 200 meters, then when the file exports, it will only be using a small percentage of the available bits to store the hight values and you might get stepping. If the maximum elevation is lowered to the actual highest part of the terrain (or if the terrain is reaching that max elevation) then you are filling up and utilizing all of the bits and you wont get stepping. You are normalizing the range for the file format. The problem we are now dealing with is how to transfer that simple file format value into an actuall height in unreal by setting the right actor scale.
The way we do this is to do something similar to what we did with the width. We make note of the maximum elevation from world machine, divide that number by 512 which fits that height into the range of the landscape system and them multiply by 100 to turn that into meters. Then that is the value which we use to set the Z-scale of the Unreal Landscape Actor.
Actor Height (z) Scale = (WorldMachineMaximumElevation/512) * 100
- Get Maximum Elevation from World Machine
- Divide that number by 512
- Multiply by 100
- Set the Z Scale of the landscape actor.
There you go. One to one mapping between World Machine and Unreal Engine 4.
So if you do these two things….
Actor Width (x & y) Scale = (Physical Distance / HeightmapResolution ) * 100
Actor Height (z) Scale = (WorldMachineMaximumElevation/512) * 100
Then you will have a happier life.