I know I can import a heightmap, but I want to do this via code. My code is fine, I can read in 8bit png’s and such, but on importing a 16bit png (or tif), I get:
Well, i’m part-way there. The result looks like it’s derived from the heightmap but isn’t quite it! I wonder if the Unity guys might be able to shed some light on it as they already have the Import RAW function!
ImportHeightmapAuto.cs
using UnityEngine;
using UnityEditor;
using System.Collections;
public class ImportHeightMapAuto : ScriptableObject
{
[MenuItem("Custom/Terrain/Import Heightmap (auto)")]
static void ImportHeightmapAuto()
{
float[,] temp = TerrainHelper.HeightToArray("Terrain_128_128", 257);
Terrain.activeTerrain.terrainData.SetHeights(0, 0, temp);
}
TerrainHelper.cs
using UnityEngine;
using System;
using System.IO;
public class TerrainHelper
{
public static int TResH;
public static int TResW;
public static float[,] HeightToArray(string TName, int TRes)
{
string FileName = TName + ".r16";
FileStream FS = new FileStream("Assets/Frontier_Height.raw", FileMode.Open, FileAccess.Read);
//FileStream FS = new FileStream("Assets/World/Terrain/" + FileName, FileMode.Open, FileAccess.Read);
int x;
int y;
float[,] HArray = new float[TRes, TRes];
BinaryReader BR = new BinaryReader(FS);
for (x = 0; x < TRes; x++)
{
for (y = 0; y < TRes; y++)
{
float Height = (float)(BR.ReadByte() / 50);
HArray[x, y] = Height;
}
}
return HArray;
}
}
At least a couple of things seem to be wrong with that script. Firstly, if the file really is using 16-bit greyscale, then the using the BinaryReader’s ReadByte function wouldn’t give the right result (BinaryReader also has a ReadInt16 function, which would seem to be necessary here). Also, this line:-
float Height = (float)(BR.ReadByte() / 50);
…doesn’t actually do what it is supposed to. The result of ReadByte is an integer value and the 50 is an integer constant, so integer division will be performed on the value and only then will it be converted to float. The line should be something like:-
float Height = (float) BR.ReadByte() / 50f;
…although, as I have said, ReadByte probably isn’t the right function to use here.