I had to find a way to edit a terrain heightmap in Gimp on a Mac which doesn’t like 16 bit as far as I can tell. Searching the forums turned up not so much. So I wrote this script to use in conjunction with Eric5h5’s apply heightmap script on the wiki.
Works fine except for a couple things:
- I didn’t try it on a scene with more than one terrain. The selection stuff was copied out of another script (the raw one?). Doesn’t look like there’s a check for multiple terrains but it didn’t matter for my project. So I’m not sure how it will behave if you have several and don’t select one.
- The biggest problem is it outputs an 8 bit image. The result is 256 levels of gray. When applying the exported PNG to a new terrain you’ll get the general shape but banding causes it to stair step. Using the smooth brush fixes it but just isn’t good enough for some(most?) projects. Scaling it down to 256 x 256 helps some but still not enough.
I went another route in the end. So, my problem’s solved. Don’t think it’s worth the wiki at this point but feel free to put it up there if you want. I’m not going to mess with it anymore. Anyone else who wants to can have at it.
Save it as HeightmapExportPNG.js and put it in an Assets/Editor folder in your project. Export Height Map as PNG should show up under the Terrain menu. Selecting it will generate a PNG and save it to the Assets folder as DuplicateHeightmap.png. See Eric’s script on the wiki to apply it to a new terrain:
import UnityEngine;
import UnityEditor;
import System.Collections;
import System.IO;
class HeightmapExportPNG extends EditorWindow
{
static var terraindata : TerrainData;
@MenuItem ("Terrain/Export Height Map as PNG")
static function Init () {
terraindata = null;
var terrain : Terrain = null;
if ( Selection.activeGameObject )
terrain = Selection.activeGameObject.GetComponent( Terrain );
if (!terrain) {
terrain = Terrain.activeTerrain;
}
if (terrain) {
terraindata = terrain.terrainData;
}
if (terraindata == null) {
EditorUtility.DisplayDialog("No terrain selected", "Please select a terrain.", "Cancel");
return;
}
//// get the terrain heights into an array and apply them to a texture2D
var myBytes : byte[];
var myIndex : int = 0;
var rawHeights = new Array(0.0,0.0);
var duplicateHeightMap = new Texture2D(terraindata.heightmapWidth, terraindata.heightmapHeight, TextureFormat.ARGB32, false);
rawHeights = terraindata.GetHeights(0, 0, terraindata.heightmapWidth, terraindata.heightmapHeight);
/// run through the array row by row
for (y=0; y < duplicateHeightMap.height; ++y)
{
for (x=0; x < duplicateHeightMap.width; ++x)
{
/// for wach pixel set RGB to the same so it's gray
var color = Vector4(rawHeights[myIndex], rawHeights[myIndex], rawHeights[myIndex], 1.0);
duplicateHeightMap.SetPixel (x, y, color);
myIndex++;
}
}
// Apply all SetPixel calls
duplicateHeightMap.Apply();
/// make it a PNG and save it to the Assets folder
myBytes = duplicateHeightMap.EncodeToPNG();
var filename : String = "DupeHeightMap.png";
File.WriteAllBytes(Application.dataPath + "/" + filename, myBytes);
EditorUtility.DisplayDialog("Heightmap Duplicated", "Saved as PNG in Assets/ as: " + filename, "");
}
}