NewN_UAVPlane/Assets/Tom's Terrain Tools/Editor/IncrementalSplatmapping.cs

310 lines
8.6 KiB
C#

using UnityEditor;
using UnityEngine;
using System.Collections;
using System.IO;
/*
Tom's Terrain Tools for Unity 3D
Incremental Splatmapping
version 1.0 - February 2015
(C)2015 by Tom Vogt <tom@lemuria.org>
http://lemuria.org/Unity/TTT/
*/
public class IncrementalSplatmapping : EditorWindow {
public Terrain MyTerrain;
public Texture2D Splatmap;
public Texture2D TextureRed;
public Texture2D TextureGreen;
public Texture2D TextureBlue;
public int TileSizeRed = 40;
public int TileSizeGreen = 40;
public int TileSizeBlue = 40;
public float bias = 1.0f;
public bool Replacing = false;
// internal variables
Vector2 scrollPosition = new Vector2(0,0);
[MenuItem("Window/Terrain Tools/Incremental Splatmapping",false,100)]
static void Init() {
IncrementalSplatmapping window = (IncrementalSplatmapping)EditorWindow.GetWindow(typeof(IncrementalSplatmapping));
window.minSize = new Vector2(400,550);
window.Show();
}
void OnInspectorUpdate() {
Repaint();
}
void OnGUI() {
EditorGUILayout.BeginVertical(GUI.skin.box, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
GUILayout.Label("Incremental Splatmapping",EditorStyles.boldLabel);
EditorGUILayout.Separator();
// bold titles
GUIStyle myFoldoutStyle = new GUIStyle(EditorStyles.foldout);
myFoldoutStyle.fontStyle = FontStyle.Bold;
EditorGUILayout.Separator();
GUILayout.BeginHorizontal();
GUILayout.Label("Terrain");
MyTerrain = (Terrain)EditorGUILayout.ObjectField("", MyTerrain, typeof(Terrain),true);
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
GUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Splatmap");
GUILayout.FlexibleSpace();
Splatmap = (Texture2D)EditorGUILayout.ObjectField("", Splatmap, typeof(Texture2D),false);
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
GUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Texture Red");
GUILayout.FlexibleSpace();
TextureRed = (Texture2D)EditorGUILayout.ObjectField("", TextureRed, typeof(Texture2D),false);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("Tile Size Red");
GUILayout.FlexibleSpace();
TileSizeRed = EditorGUILayout.IntSlider(TileSizeRed, 4, 512);
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
GUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Texture Green");
GUILayout.FlexibleSpace();
TextureGreen = (Texture2D)EditorGUILayout.ObjectField("", TextureGreen, typeof(Texture2D),false);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("Tile Size Green");
GUILayout.FlexibleSpace();
TileSizeGreen = EditorGUILayout.IntSlider(TileSizeGreen, 4, 512);
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
GUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Texture Blue");
GUILayout.FlexibleSpace();
TextureBlue = (Texture2D)EditorGUILayout.ObjectField("", TextureBlue, typeof(Texture2D),false);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("Tile Size Blue");
GUILayout.FlexibleSpace();
TileSizeBlue = EditorGUILayout.IntSlider(TileSizeBlue, 4, 512);
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
GUILayout.BeginHorizontal();
GUILayout.Label("Strength of this layer");
GUILayout.FlexibleSpace();
bias = EditorGUILayout.Slider(bias, 0.1f, 10.0f);
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
GUILayout.BeginHorizontal();
GUILayout.Label("replace old textures");
GUILayout.FlexibleSpace();
Replacing = EditorGUILayout.Toggle ("", Replacing);
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Add Splat Texture",GUILayout.Width(200), GUILayout.Height(32))) {
if (CheckSplatmap()) {
AddSplatTexture();
}
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
EditorGUILayout.EndScrollView();
EditorGUILayout.EndVertical();
}
void FixFormat(Texture2D texture) {
string path = AssetDatabase.GetAssetPath(texture);
TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
if (texture.format != TextureFormat.RGB24 || !textureImporter.isReadable)
{
textureImporter.mipmapEnabled = false;
textureImporter.isReadable = true;
textureImporter.textureFormat = TextureImporterFormat.RGB24;
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
Debug.Log("fixed texture format for "+path);
}
}
public string Reverse(string text) {
if (text == null) return null;
// this was posted by petebob as well
char[] array = text.ToCharArray();
System.Array.Reverse(array);
return new string(array);
}
public string FindFile(string basename) {
string[] extensions = {"tif", "tiff", "png", "jpg", "jpeg"};
foreach (string ext in extensions) {
string filename = basename + "." + ext;
if (File.Exists(filename)) {
return filename;
}
}
return "";
}
bool CheckSplatmap() {
if (Splatmap==null) return false;
FixFormat(Splatmap);
if (Splatmap.height != Splatmap.width) {
EditorUtility.DisplayDialog("Wrong size", "Splatmap must be square (width and height must be the same)", "Cancel");
return false;
}
if (Mathf.ClosestPowerOfTwo(Splatmap.width) != Splatmap.width) {
EditorUtility.DisplayDialog("Wrong size", "Splatmap width and height must be a power of two", "Cancel");
return false;
}
return true;
}
void AddSplatTexture()
{
if (!MyTerrain) MyTerrain = Terrain.activeTerrain;
TerrainData terrain = MyTerrain.terrainData;
int splaMaptWidth = Splatmap.width;
if (splaMaptWidth!=terrain.alphamapWidth)
{
Debug.LogError("New splatmap is not same resolution as the current terrain splatmap ("+splaMaptWidth+" != "+terrain.alphamapWidth+")");
return;
}
Undo.RecordObject(terrain, "Add Splattexture");
Color[] SplatmapColors = Splatmap.GetPixels();
int layer = MyTerrain.terrainData.alphamapLayers;
int add_layers = 0;
int red_layer = layer;
int green_layer = layer+1;
int blue_layer = layer+2;
if (TextureRed) {
AddTexture(TextureRed, TileSizeRed);
add_layers++;
}
if (TextureGreen) {
AddTexture(TextureGreen, TileSizeGreen);
green_layer = layer + add_layers;
add_layers++;
}
if (TextureBlue) {
AddTexture(TextureBlue, TileSizeBlue);
blue_layer = layer + add_layers;
add_layers++;
}
float[,,] splatmapData = terrain.GetAlphamaps(0, 0, splaMaptWidth, splaMaptWidth);
for (int y = 0; y < splaMaptWidth; y++) {
if (y%10 == 0) {
EditorUtility.DisplayProgressBar("add splat", "updating terrain", Mathf.InverseLerp(0.0f, (float)splaMaptWidth, (float)y));
}
for (int x = 0; x < splaMaptWidth; x++) {
float red = SplatmapColors[x*splaMaptWidth + y].r * bias;
float green = SplatmapColors[x*splaMaptWidth + y].g * bias;
float blue = SplatmapColors[x*splaMaptWidth + y].b * bias;
float value = 0.0f;
if (TextureRed) {
if (red>0.0f) {
splatmapData[x,y,red_layer] = red;
value+=red;
} else {
splatmapData[x,y,red_layer] = 0.0f;
}
}
if (TextureGreen) {
if (green>0.0f) {
splatmapData[x,y,green_layer] = green;
value+=green;
} else {
splatmapData[x,y,green_layer] = 0.0f;
}
}
if (TextureBlue) {
if (blue>0.0f) {
splatmapData[x,y,blue_layer] = blue;
value+=blue;
} else {
splatmapData[x,y,blue_layer] = 0.0f;
}
}
// normalize
float total = 0.0f;
for (int l = 0; l < layer+add_layers; l++) {
if (Replacing && value >= 1.0f && l < layer) {
splatmapData[x,y,l] = 0;
}
total += splatmapData[x,y,l];
}
if (total != 1.0f) {
for (int l = 0; l < layer+add_layers; l++) {
splatmapData[x,y,l] *= 1.0f/total;
}
}
}
}
terrain.SetAlphamaps(0, 0, splatmapData);
EditorUtility.SetDirty(MyTerrain);
Debug.Log("Splatmap texture applied");
EditorUtility.ClearProgressBar();
}
void AddTexture(Texture2D Texture, int TileSize)
{
SplatPrototype[] oldPrototypes = MyTerrain.terrainData.splatPrototypes;
SplatPrototype[] newPrototypes = new SplatPrototype[oldPrototypes.Length + 1];
for (int x=0;x<oldPrototypes.Length;x++) {
newPrototypes[x] = oldPrototypes[x];
}
newPrototypes[oldPrototypes.Length] = new SplatPrototype();
newPrototypes[oldPrototypes.Length].texture = Texture;
Vector2 vector = new Vector2(TileSize, TileSize);
newPrototypes[oldPrototypes.Length].tileSize = vector;
MyTerrain.terrainData.splatPrototypes = newPrototypes;
}
}