- Home /
I've written a script to create dynamic height maps. How do I use those height maps to generate dynamic procedural terrains?
Hello everyone,
I've written a few scripts that make dynamic procedural height maps based on perline noise. This works great! I followed another tutorial that showed me how to convert those height maps into meshes which works great! Here is an image of a map I generated procedurally.
[img]http://i.imgur.com/1YquORX.png[/img]
However I've quickly come to realize that meshes do not make for the best terrains because of their limitations. Specifically I want to procedurally texture the map and place bushes etc. Everything I have read has said that terrains are a better type for this kind of application!
However I'm having trouble gaining any traction on how to implement a dynamic height map onto a terrain. There are plenty of resources I can read on how to do it manually, or how to import height maps etc. This isn't what I want.
So my question is, given that I already have a height map stored in a normalized 2d array how do I transfer that height map to a terrain at runtime?
public static void GenerateTerrainMesh(float [,] heightMap) {
Terrain mapTerrain = Terrain.activeTerrain; //Get the active terrain (make sure you only have 1 terrain in the scene)
TerrainData terrainData = mapTerrain.terrainData;
int width = heightMap.GetLength (0);
int height = heightMap.GetLength (1);
terrainData.size = new Vector3 (width, 1, height);
terrainData.SetHeights (0, 0, heightMap);
}
Please not that I have manually placed a terrain object into my scene so I don't need to (I don't think?) dynamically create one.
That little bit of code is where I've gotten to after all my ready and trial and errors. I know it's not much but you can see what I'm trying to do.
Thank you so much to anyone who can help me!
I should note that my code posted above...works kinda. I can see some height to the terrain map once I run that code but it's very small and only in the bottom left hand cornder. If that helps at all.
Answer by tanoshimi · Sep 11, 2016 at 07:02 AM
That suggests that the dimensions of your heightMap array do not match the dimensions of your terrain. (note that that is not what line 10 does - that sets the size of the terrain, not the size of the heightmap).
The heightMap array should be a square, power of two +1, e.g. 513x513, 1025x1025, which matches the resolution of the terrain component set in the inspector. Is that the case?
You are probably correct @tanoshimi and I had that feeling after digging into it more. The scales seem off.
So let me get this straight:
I need to create a height map that is, for example, 129x129.
$$anonymous$$y TerrainData.Size should be equal to 129 x Height x 129 in dimension?
Here is what I have in the pics below. I think that's what I'm doing but it's still co$$anonymous$$g up weird on the terrain.
[img]http://imgur.com/sOeIk8B[/img] [img]http://imgur.com/2ChtQok[/img]
And here is the code that copies the heightmap you see in pic 1 to the terrain you see on the left
public static void GenerateTerrain$$anonymous$$esh(float [,] height$$anonymous$$ap, float highestPoint, float lowestPoint) {
Terrain mapTerrain = Terrain.activeTerrain; //Get the active terrain (make sure you only have 1 terrain in the scene)
TerrainData terrainData = mapTerrain.terrainData;
terrainData.SetHeights (0, 0, height$$anonymous$$ap);
}
I have a feeling like I'm missing something stupid but I can't see it!
The TerrainData.size can be anything you want. It will just scale the terrain and not affect the SetHeights in any way.
TerrainData.heightmapResolution should match the array before using SetHeights. The array can be smaller than the resolution and then only part of the existing heightmap will be overwritten. (or if you pass other than zeroes as the starting point) If the array is larger, then it will throw an error.
So when the TerrainData.size is equal to the heightmap resolution, then it will be unscaled. In most cases the array you're passing to SetHeights should match the resolution.
Ok. I think I'm understanding this.
In simple terms the TerrainData.Size deter$$anonymous$$es the size of the map in world units? And the TerrainData.height$$anonymous$$apResolution member controls how the map scales in relations to the height map? IE a larger map would require a larger resolution or else it would lose a bunch of its details?
Then I have a follow up question. How would I go about (logically) calculating the height of the TerrainData.Size member? IE TerrainData.Size = new Vector3(1000, ???, 1000) based off my height map?
Thank you for your time @villevli