diff --git a/Assets/Editor/TransferFunction2DEditorWindow.cs b/Assets/Editor/TransferFunction2DEditorWindow.cs index 4f4a629..15bc3f7 100644 --- a/Assets/Editor/TransferFunction2DEditorWindow.cs +++ b/Assets/Editor/TransferFunction2DEditorWindow.cs @@ -107,7 +107,7 @@ namespace UnityVolumeRendering } // Add new rectangle - if (GUI.Button(new Rect(startX, startY + 100, 150.0f, 40.0f), "Add rectangle")) + if (GUI.Button(new Rect(startX, startY + 100, 110.0f, 30.0f), "Add rectangle")) { tf2d.AddBox(0.1f, 0.1f, 0.8f, 0.8f, Color.white, 0.5f); needsRegenTexture = true; @@ -115,19 +115,40 @@ namespace UnityVolumeRendering // Remove selected shape if (selectedBoxIndex != -1) { - if (GUI.Button(new Rect(startX, startY + 150, 150.0f, 40.0f), "Remove selected shape")) + if (GUI.Button(new Rect(startX, startY + 140, 110.0f, 30.0f), "Remove selected shape")) { tf2d.boxes.RemoveAt(selectedBoxIndex); needsRegenTexture = true; } } + if(GUI.Button(new Rect(startX, startY + 180, 110.0f, 30.0f), "Save")) + { + string filepath = EditorUtility.SaveFilePanel("Save transfer function", "", "default.tf2d", "tf2d"); + if(filepath != "") + TransferFunctionDatabase.SaveTransferFunction2D(tf2d, filepath); + } + if(GUI.Button(new Rect(startX, startY + 220, 110.0f, 30.0f), "Load")) + { + string filepath = EditorUtility.OpenFilePanel("Save transfer function", "", "tf2d"); + if(filepath != "") + { + TransferFunction2D newTF = TransferFunctionDatabase.LoadTransferFunction2D(filepath); + if(newTF != null) + { + volRendObject.transferFunction2D = tf2d = newTF; + needsRegenTexture = true; + } + } + } + // TODO: regenerate on add/remove/modify (and do it async) if (needsRegenTexture) { tf2d.GenerateTexture(); needsRegenTexture = false; } + // TODO: volRendObject.GetComponent().sharedMaterial.SetTexture("_TFTex", tf2d.GetTexture()); volRendObject.GetComponent().sharedMaterial.EnableKeyword("TF2D_ON"); diff --git a/Assets/Editor/TransferFunctionEditorWindow.cs b/Assets/Editor/TransferFunctionEditorWindow.cs index 282cc1d..7218e68 100644 --- a/Assets/Editor/TransferFunctionEditorWindow.cs +++ b/Assets/Editor/TransferFunctionEditorWindow.cs @@ -64,9 +64,13 @@ namespace UnityVolumeRendering Event currentEvent = new Event(Event.current); Color oldColour = GUI.color; - float bgWidth = Mathf.Min(this.position.width - 20.0f, (this.position.height - 50.0f) * 2.0f); - Rect bgRect = new Rect(0.0f, 0.0f, bgWidth, bgWidth * 0.5f); + + float contentWidth = Mathf.Min(this.position.width - 20.0f, (this.position.height - 100.0f) * 2.0f); + float contentHeight = contentWidth * 0.5f; + + Rect bgRect = new Rect(0.0f, 0.0f, contentWidth, contentHeight); + // TODO: tf.GenerateTexture(); tfGUIMat.SetTexture("_TFTex", tf.GetTexture()); @@ -161,11 +165,29 @@ namespace UnityVolumeRendering if (selectedColPointIndex != -1) { TFColourControlPoint colPoint = tf.colourControlPoints[selectedColPointIndex]; - colPoint.colourValue = EditorGUI.ColorField(new Rect(bgRect.x, bgRect.y + bgRect.height + 50, 100.0f, 40.0f), colPoint.colourValue); + colPoint.colourValue = EditorGUI.ColorField(new Rect(150, bgRect.y + bgRect.height + 50, 100.0f, 40.0f), colPoint.colourValue); tf.colourControlPoints[selectedColPointIndex] = colPoint; } - GUI.skin.label.wordWrap = false; - GUI.Label(new Rect(0.0f, bgRect.y + bgRect.height + 60.0f, 700.0f, 30.0f), "Left click to select and move a control point. Right click to add a control point, and ctrl + right click to delete."); + + if(GUI.Button(new Rect(0.0f, bgRect.y + bgRect.height + 50.0f, 70.0f, 30.0f), "Save")) + { + string filepath = EditorUtility.SaveFilePanel("Save transfer function", "", "default.tf", "tf"); + if(filepath != "") + TransferFunctionDatabase.SaveTransferFunction(tf, filepath); + } + if(GUI.Button(new Rect(75.0f, bgRect.y + bgRect.height + 50.0f, 70.0f, 30.0f), "Load")) + { + string filepath = EditorUtility.OpenFilePanel("Save transfer function", "", "tf"); + if(filepath != "") + { + TransferFunction newTF = TransferFunctionDatabase.LoadTransferFunction(filepath); + if(newTF != null) + volRendObject.transferFunction = tf = newTF; + } + } + + GUI.skin.label.wordWrap = false; + GUI.Label(new Rect(0.0f, bgRect.y + bgRect.height + 85.0f, 700.0f, 30.0f), "Left click to select and move a control point. Right click to add a control point, and ctrl + right click to delete."); // TEST!!! TODO volRendObject.GetComponent().sharedMaterial.SetTexture("_TFTex", tfTexture); diff --git a/Assets/Scripts/TransferFunction/TFControlPoints.cs b/Assets/Scripts/TransferFunction/TFControlPoints.cs index 843a2de..1ae2025 100644 --- a/Assets/Scripts/TransferFunction/TFControlPoints.cs +++ b/Assets/Scripts/TransferFunction/TFControlPoints.cs @@ -2,6 +2,7 @@ namespace UnityVolumeRendering { + [System.Serializable] public struct TFColourControlPoint { public float dataValue; @@ -14,6 +15,7 @@ namespace UnityVolumeRendering } } + [System.Serializable] public struct TFAlphaControlPoint { public float dataValue; diff --git a/Assets/Scripts/TransferFunction/TransferFunction2D.cs b/Assets/Scripts/TransferFunction/TransferFunction2D.cs index d5bddee..11b657f 100644 --- a/Assets/Scripts/TransferFunction/TransferFunction2D.cs +++ b/Assets/Scripts/TransferFunction/TransferFunction2D.cs @@ -4,8 +4,9 @@ using UnityEngine; namespace UnityVolumeRendering { - public class TransferFunction2D : MonoBehaviour + public class TransferFunction2D { + [System.Serializable] public struct TF2DBox { public Color colour; diff --git a/Assets/Scripts/TransferFunction/TransferFunctionDatabase.cs b/Assets/Scripts/TransferFunction/TransferFunctionDatabase.cs new file mode 100644 index 0000000..cffe121 --- /dev/null +++ b/Assets/Scripts/TransferFunction/TransferFunctionDatabase.cs @@ -0,0 +1,104 @@ +using UnityEngine; +using System.Collections.Generic; +using System.IO; + +namespace UnityVolumeRendering +{ + public class TransferFunctionDatabase + { + [System.Serializable] + private struct TF1DSerialisationData + { + public int version; + public List colourPoints; + public List alphaPoints; + + public const int VERSION_ID = 1; + } + + [System.Serializable] + private struct TF2DSerialisationData + { + public int version; + public List boxes; + + public const int VERSION_ID = 1; + } + + public static TransferFunction CreateTransferFunction() + { + TransferFunction tf = new TransferFunction(); + tf.AddControlPoint(new TFColourControlPoint(0.0f, new Color(0.11f, 0.14f, 0.13f, 1.0f))); + tf.AddControlPoint(new TFColourControlPoint(0.2415f, new Color(0.469f, 0.354f, 0.223f, 1.0f))); + tf.AddControlPoint(new TFColourControlPoint(0.3253f, new Color(1.0f, 1.0f, 1.0f, 1.0f))); + + tf.AddControlPoint(new TFAlphaControlPoint(0.0f, 0.0f)); + tf.AddControlPoint(new TFAlphaControlPoint(0.1787f, 0.0f)); + tf.AddControlPoint(new TFAlphaControlPoint(0.2f, 0.024f)); + tf.AddControlPoint(new TFAlphaControlPoint(0.28f, 0.03f)); + tf.AddControlPoint(new TFAlphaControlPoint(0.4f, 0.546f)); + tf.AddControlPoint(new TFAlphaControlPoint(0.547f, 0.5266f)); + + tf.GenerateTexture(); + return tf; + } + + public static TransferFunction2D CreateTransferFunction2D() + { + TransferFunction2D tf2D = new TransferFunction2D(); + tf2D.AddBox(0.05f, 0.1f, 0.8f, 0.7f, Color.white, 0.4f); + return tf2D; + } + + public static TransferFunction LoadTransferFunction(string filepath) + { + if(!File.Exists(filepath)) + { + Debug.LogError(string.Format("File does not exist: {0}", filepath)); + return null; + } + string jsonstring = File.ReadAllText(filepath); + TF1DSerialisationData data = JsonUtility.FromJson(jsonstring); + Debug.Log(jsonstring); + Debug.Log(data.colourPoints.ToString()); + Debug.Log(data.alphaPoints.ToString()); + TransferFunction tf = new TransferFunction(); + tf.colourControlPoints = data.colourPoints; + tf.alphaControlPoints = data.alphaPoints; + return tf; + } + + public static TransferFunction2D LoadTransferFunction2D(string filepath) + { + if(!File.Exists(filepath)) + { + Debug.LogError(string.Format("File does not exist: {0}", filepath)); + return null; + } + string jsonstring = File.ReadAllText(filepath); + TF2DSerialisationData data = JsonUtility.FromJson(jsonstring); + TransferFunction2D tf = new TransferFunction2D(); + tf.boxes = data.boxes; + return tf; + } + + public static void SaveTransferFunction(TransferFunction tf, string filepath) + { + TF1DSerialisationData data = new TF1DSerialisationData(); + data.version = TF1DSerialisationData.VERSION_ID; + data.colourPoints = new List(tf.colourControlPoints); + data.alphaPoints = new List(tf.alphaControlPoints); + string jsonstring = JsonUtility.ToJson(data); + File.WriteAllText(filepath, jsonstring); + } + + public static void SaveTransferFunction2D(TransferFunction2D tf2d, string filepath) + { + TF2DSerialisationData data = new TF2DSerialisationData(); + data.version = TF2DSerialisationData.VERSION_ID; + data.boxes = new List(tf2d.boxes); + string jsonstring = JsonUtility.ToJson(data); + File.WriteAllText(filepath, jsonstring); + } + } +} diff --git a/Assets/Scripts/VolumeObject/VolumeObjectFactory.cs b/Assets/Scripts/VolumeObject/VolumeObjectFactory.cs index 38996ee..2c91af7 100644 --- a/Assets/Scripts/VolumeObject/VolumeObjectFactory.cs +++ b/Assets/Scripts/VolumeObject/VolumeObjectFactory.cs @@ -53,26 +53,13 @@ namespace UnityVolumeRendering const int noiseDimY = 512; Texture2D noiseTexture = NoiseTextureGenerator.GenerateNoiseTexture(noiseDimX, noiseDimY); - TransferFunction tf = new TransferFunction(); - tf.AddControlPoint(new TFColourControlPoint(0.0f, new Color(0.11f, 0.14f, 0.13f, 1.0f))); - tf.AddControlPoint(new TFColourControlPoint(0.2415f, new Color(0.469f, 0.354f, 0.223f, 1.0f))); - tf.AddControlPoint(new TFColourControlPoint(0.3253f, new Color(1.0f, 1.0f, 1.0f, 1.0f))); - - tf.AddControlPoint(new TFAlphaControlPoint(0.0f, 0.0f)); - tf.AddControlPoint(new TFAlphaControlPoint(0.1787f, 0.0f)); - tf.AddControlPoint(new TFAlphaControlPoint(0.2f, 0.024f)); - tf.AddControlPoint(new TFAlphaControlPoint(0.28f, 0.03f)); - tf.AddControlPoint(new TFAlphaControlPoint(0.4f, 0.546f)); - tf.AddControlPoint(new TFAlphaControlPoint(0.547f, 0.5266f)); - - tf.GenerateTexture(); + TransferFunction tf = TransferFunctionDatabase.CreateTransferFunction(); Texture2D tfTexture = tf.GetTexture(); volObj.transferFunction = tf; tf.histogramTexture = HistogramTextureGenerator.GenerateHistogramTexture(dataset); - TransferFunction2D tf2D = new TransferFunction2D(); - tf2D.AddBox(0.05f, 0.1f, 0.8f, 0.7f, Color.white, 0.4f); + TransferFunction2D tf2D = TransferFunctionDatabase.CreateTransferFunction2D(); volObj.transferFunction2D = tf2D; meshRenderer.sharedMaterial.SetTexture("_DataTex", tex);