If I call terrainData.GetAlphamapTexture() I get a Texture2D. How would I then load that back into terrainData? SetAlphamaps requires a float[,].
Ok, figured it out. I was specifically having a problem with the CTS splat maps being in a texture on the material’s shader. (Or in the CTS component.) This will pull those splat maps and write them to the terrain data. Geez, took me 6 hours…
At least it’s done.
private void DoExport()
{
#if UNITY_EDITOR
var sceneName = SceneManager.GetActiveScene().name;
var timeText = DateTime.Now.ToString("HHmmss");
var path = "Assets/Scenes/" + sceneName + "/TerrainData-" + timeText + ".asset";
Debug.Log("Saving to: " + path);
var terrain = GetComponent<Terrain>();
var terrainData = terrain.terrainData;
// Write the CTS splat map to the terrainData!
var splats = GenerateCtsAlphamap(terrainData);
UnityEditor.AssetDatabase.CreateAsset(terrainData, path);
// It is necessary to re-set and save. Unity issue?
terrainData.SetAlphamaps(0, 0, splats);
UnityEditor.AssetDatabase.SaveAssets();
#endif
}
private float[,,] GenerateCtsAlphamap(TerrainData terrainData)
{
var cts = GetComponent<CompleteTerrainShader>();
var splatList = new[] {cts.Splat1, cts.Splat2, cts.Splat3, cts.Splat4};
// Ensure we have the correct size array.
var myMap = terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight);
// When we have a second splat. Two splats of 4 layers = 8.
// var myMap = new float[terrainData.alphamapWidth, terrainData.alphamapHeight, 8];
var layerCount = myMap.GetLength(2);
for (var splatId = 0; splatId < 4; splatId++)
{
var tex = splatList[splatId];
if (tex == null) continue;
var colors = splatList[splatId].GetPixels();
for (var x = 0; x < terrainData.alphamapWidth; x++)
{
for (var y = 0; y < terrainData.alphamapHeight; y++)
{
// First splat will go in slots 0, 1, 2, 3
// Second splat will go in slots 4, 5, 6, 7
// Texture is 513, vs alphamap is 512. This is ok, ignore the 513th element.
// RGBA (Assume height and width are equal.)
myMap[x, y, splatId * 4 + 0] = colors[x * splatList[splatId].width + y].r;
if (layerCount <= splatId * 4 + 1) continue;
myMap[x, y, splatId * 4 + 1] = colors[x * splatList[splatId].width + y].g;
if (layerCount <= splatId * 4 + 2) continue;
myMap[x, y, splatId * 4 + 2] = colors[x * splatList[splatId].width + y].b;
// Sometimes there are 7 layers, so we have no where to place the 8th layer.
if (layerCount <= splatId * 4 + 3) continue;
myMap[x, y, splatId * 4 + 3] = colors[x * splatList[splatId].width + y].a;
}
}
}
return myMap;
}
1 Like