private void OnOpenDICOMDatasetResult(RuntimeFileBrowser.DialogResult result) { if (!result.cancelled) { // We'll only allow one dataset at a time in the runtime GUI (for simplicity) DespawnAllDatasets(); bool recursive = true; // Read all files IEnumerable <string> fileCandidates = Directory.EnumerateFiles(result.path, "*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly) .Where(p => p.EndsWith(".dcm", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicom", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicm", StringComparison.InvariantCultureIgnoreCase)); // Import the dataset DICOMImporter importer = new DICOMImporter(fileCandidates, Path.GetFileName(result.path)); List <DICOMImporter.DICOMSeries> seriesList = importer.LoadDICOMSeries(); float numVolumesCreated = 0; foreach (DICOMImporter.DICOMSeries series in seriesList) { VolumeDataset dataset = importer.ImportDICOMSeries(series); // Spawn the object if (dataset != null) { VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); obj.transform.position = new Vector3(numVolumesCreated, 0, 0); numVolumesCreated++; } } } }
public static void ImportDataset(string filePath) { DatasetType datasetType = DatasetImporterUtility.GetDatasetType(filePath); switch (datasetType) { case DatasetType.Raw: { RAWDatasetImporterEditorWindow wnd = (RAWDatasetImporterEditorWindow)EditorWindow.GetWindow(typeof(RAWDatasetImporterEditorWindow)); if (wnd != null) { wnd.Close(); } wnd = new RAWDatasetImporterEditorWindow(filePath); wnd.Show(); break; } case DatasetType.DICOM: { DatasetImporterBase importer = new DICOMImporter(new FileInfo(filePath).Directory.FullName, false); VolumeDataset dataset = importer.Import(); if (dataset != null) { VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); } break; } } }
private void OnGUI() { // Update selected object VolumeRenderedObject volRendObject = SelectionHelper.GetSelectedVolumeObject(); if (volRendObject == null) { volRendObject = GameObject.FindObjectOfType <VolumeRenderedObject>(); } if (volRendObject == null) { return; } EditorGUILayout.LabelField("Edit the visible value range (min/max value) with the slider."); Vector2 visibilityWindow = volRendObject.GetVisibilityWindow(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.MinMaxSlider("Visible value range", ref visibilityWindow.x, ref visibilityWindow.y, 0.0f, 1.0f); EditorGUILayout.Space(); EditorGUILayout.Space(); EditorGUILayout.EndHorizontal(); volRendObject.SetVisibilityWindow(visibilityWindow); }
static void ShowDICOMImporter() { string dir = EditorUtility.OpenFolderPanel("Select a folder to load", "", ""); if (Directory.Exists(dir)) { bool recursive = true; // Read all files IEnumerable <string> fileCandidates = Directory.EnumerateFiles(dir, "*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly) .Where(p => p.EndsWith(".dcm", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicom", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicm", StringComparison.InvariantCultureIgnoreCase)); if (!fileCandidates.Any()) { #if UNITY_EDITOR if (UnityEditor.EditorUtility.DisplayDialog("Could not find any DICOM files", $"Failed to find any files with DICOM file extension.{Environment.NewLine}Do you want to include files without DICOM file extension?", "Yes", "No")) { fileCandidates = Directory.EnumerateFiles(dir, "*.*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly); } #endif } if (fileCandidates.Any()) { DICOMImporter importer = new DICOMImporter(fileCandidates, Path.GetFileName(dir)); List <DICOMImporter.DICOMSeries> seriesList = importer.LoadDICOMSeries(); float numVolumesCreated = 0; foreach (DICOMImporter.DICOMSeries series in seriesList) { VolumeDataset dataset = importer.ImportDICOMSeries(series); if (dataset != null) { if (EditorPrefs.GetBool("DownscaleDatasetPrompt")) { if (EditorUtility.DisplayDialog("Optional DownScaling", $"Do you want to downscale the dataset? The dataset's dimension is: {dataset.dimX} x {dataset.dimY} x {dataset.dimZ}", "Yes", "No")) { dataset.DownScaleData(); } } VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); obj.transform.position = new Vector3(numVolumesCreated, 0, 0); numVolumesCreated++; } } } else { Debug.LogError("Could not find any DICOM files to import."); } } else { Debug.LogError("Directory doesn't exist: " + dir); } }
private void OnSelectionChange() { VolumeRenderedObject newVolRendObj = Selection.activeGameObject?.GetComponent <VolumeRenderedObject>(); // If we selected another volume object than the one previously edited in this GUI if (volRendObject != null && newVolRendObj != null && newVolRendObj != volRendObject) { this.Close(); } }
public static void ShowWindow(VolumeRenderedObject volRendObj) { if (instance != null) { GameObject.Destroy(instance); } GameObject obj = new GameObject($"EditVolumeGUI_{volRendObj.name}"); instance = obj.AddComponent <EditVolumeGUI>(); instance.targetObject = volRendObj; }
public override void OnInspectorGUI() { VolumeRenderedObject myTarget = (VolumeRenderedObject)target; RenderMode oldRenderMode = myTarget.GetRenderMode(); RenderMode newRenderMode = (RenderMode)EditorGUILayout.EnumPopup("Render mode", oldRenderMode); if (newRenderMode != oldRenderMode) { myTarget.SetRenderMode(newRenderMode); } }
public static VolumeRenderedObject GetSelectedVolumeObject() { foreach (GameObject obj in Selection.gameObjects) { VolumeRenderedObject volrendobj = obj.GetComponent <VolumeRenderedObject>(); if (volrendobj != null) { return(volrendobj); } } return(null); }
private static void SpawnCrossSectionPlane(VolumeRenderedObject volobj) { GameObject quad = GameObject.CreatePrimitive(PrimitiveType.Quad); quad.transform.rotation = Quaternion.Euler(270.0f, 0.0f, 0.0f); SlicingPlaneAnyDirection csplane = quad.gameObject.AddComponent <SlicingPlaneAnyDirection>(); csplane.mat = volobj.GetComponent <MeshRenderer>().sharedMaterial; csplane.volumeTransform = volobj.transform; quad.transform.position = volobj.transform.position; Selection.objects = new Object[] { quad }; }
public override void OnInspectorGUI() { VolumeRenderedObject volrendObj = (VolumeRenderedObject)target; // Render mode RenderMode oldRenderMode = volrendObj.GetRenderMode(); RenderMode newRenderMode = (RenderMode)EditorGUILayout.EnumPopup("Render mode", oldRenderMode); if (newRenderMode != oldRenderMode) { volrendObj.SetRenderMode(newRenderMode); } // Lighting settings if (volrendObj.GetRenderMode() == RenderMode.DirectVolumeRendering) { volrendObj.SetLightingEnabled(GUILayout.Toggle(volrendObj.GetLightingEnabled(), "Enable lighting")); } else { volrendObj.SetLightingEnabled(false); } // Visibility window Vector2 visibilityWindow = volrendObj.GetVisibilityWindow(); EditorGUILayout.MinMaxSlider("Visible value range", ref visibilityWindow.x, ref visibilityWindow.y, 0.0f, 1.0f); EditorGUILayout.Space(); volrendObj.SetVisibilityWindow(visibilityWindow); // Transfer function type TFRenderMode tfMode = (TFRenderMode)EditorGUILayout.EnumPopup("Transfer function type", volrendObj.GetTransferFunctionMode()); if (tfMode != volrendObj.GetTransferFunctionMode()) { volrendObj.SetTransferFunctionMode(tfMode); } // Show TF button if (GUILayout.Button("Edit transfer function")) { if (tfMode == TFRenderMode.TF1D) { TransferFunctionEditorWindow.ShowWindow(); } else { TransferFunction2DEditorWindow.ShowWindow(); } } }
public static void SpawnCutoutBox(VolumeRenderedObject volobj) { GameObject obj = GameObject.Instantiate((GameObject)Resources.Load("CutoutBox")); obj.transform.rotation = Quaternion.Euler(270.0f, 0.0f, 0.0f); CutoutBox cbox = obj.gameObject.GetComponent <CutoutBox>(); cbox.targetObject = volobj; obj.transform.position = volobj.transform.position; #if UNITY_EDITOR UnityEditor.Selection.objects = new UnityEngine.Object[] { obj }; #endif }
public static void SpawnCrossSectionPlane(VolumeRenderedObject volobj) { GameObject quad = GameObject.Instantiate((GameObject)Resources.Load("CrossSectionPlane")); quad.transform.rotation = Quaternion.Euler(270.0f, 0.0f, 0.0f); CrossSectionPlane csplane = quad.gameObject.GetComponent <CrossSectionPlane>(); csplane.targetObject = volobj; quad.transform.position = volobj.transform.position; #if UNITY_EDITOR UnityEditor.Selection.objects = new UnityEngine.Object[] { quad }; #endif }
public static void SpawnCrossSectionPlane(VolumeRenderedObject volobj) { GameObject quad = GameObject.CreatePrimitive(PrimitiveType.Quad); quad.transform.rotation = Quaternion.Euler(270.0f, 0.0f, 0.0f); CrossSectionPlane csplane = quad.gameObject.AddComponent <CrossSectionPlane>(); csplane.targetObject = volobj; quad.transform.position = volobj.transform.position; #if UNITY_EDITOR UnityEditor.Selection.objects = new UnityEngine.Object[] { quad }; #endif }
public static VolumeRenderedObject CreateObject(VolumeDataset dataset) { GameObject outerObject = new GameObject("VolumeRenderedObject_" + dataset.datasetName); VolumeRenderedObject volObj = outerObject.AddComponent <VolumeRenderedObject>(); GameObject meshContainer = GameObject.Instantiate((GameObject)Resources.Load("VolumeContainer")); meshContainer.transform.parent = outerObject.transform; meshContainer.transform.localScale = Vector3.one; meshContainer.transform.localPosition = Vector3.zero; meshContainer.transform.parent = outerObject.transform; outerObject.transform.localRotation = Quaternion.Euler(90.0f, 0.0f, 0.0f); MeshRenderer meshRenderer = meshContainer.GetComponent <MeshRenderer>(); meshRenderer.sharedMaterial = new Material(meshRenderer.sharedMaterial); volObj.meshRenderer = meshRenderer; volObj.dataset = dataset; const int noiseDimX = 512; const int noiseDimY = 512; Texture2D noiseTexture = NoiseTextureGenerator.GenerateNoiseTexture(noiseDimX, noiseDimY); TransferFunction tf = TransferFunctionDatabase.CreateTransferFunction(); Texture2D tfTexture = tf.GetTexture(); volObj.transferFunction = tf; TransferFunction2D tf2D = TransferFunctionDatabase.CreateTransferFunction2D(); volObj.transferFunction2D = tf2D; meshRenderer.sharedMaterial.SetTexture("_DataTex", dataset.GetDataTexture()); meshRenderer.sharedMaterial.SetTexture("_GradientTex", null); meshRenderer.sharedMaterial.SetTexture("_NoiseTex", noiseTexture); meshRenderer.sharedMaterial.SetTexture("_TFTex", tfTexture); meshRenderer.sharedMaterial.EnableKeyword("MODE_DVR"); meshRenderer.sharedMaterial.DisableKeyword("MODE_MIP"); meshRenderer.sharedMaterial.DisableKeyword("MODE_SURF"); if (dataset.scaleX != 0.0f && dataset.scaleY != 0.0f && dataset.scaleZ != 0.0f) { float maxScale = Mathf.Max(dataset.scaleX, dataset.scaleY, dataset.scaleZ); volObj.transform.localScale = new Vector3(dataset.scaleX / maxScale, dataset.scaleY / maxScale, dataset.scaleZ / maxScale); } return(volObj); }
private void OnEnable() { tfGUIMat = Resources.Load <Material>("TransferFunction2DGUIMat"); volRendObject = SelectionHelper.GetSelectedVolumeObject(); if (volRendObject == null) { volRendObject = GameObject.FindObjectOfType <VolumeRenderedObject>(); if (volRendObject != null) { Selection.objects = new Object[] { volRendObject.gameObject } } ; } }
private void ImportDataset() { DatasetImporterBase importer = new RawDatasetImporter(fileToImport, dimX, dimY, dimZ, dataFormat, endianness, bytesToSkip); VolumeDataset dataset = importer.Import(); if (dataset != null) { VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); } else { Debug.LogError("Failed to import datset"); } this.Close(); }
public override void OnInspectorGUI() { VolumeRenderedObject volrendObj = (VolumeRenderedObject)target; RenderMode oldRenderMode = volrendObj.GetRenderMode(); RenderMode newRenderMode = (RenderMode)EditorGUILayout.EnumPopup("Render mode", oldRenderMode); if (newRenderMode == RenderMode.IsosurfaceRendering) { Material mat = volrendObj.GetComponent <MeshRenderer>().sharedMaterial; // TODO float minVal = mat.GetFloat("_MinVal"); float maxVal = mat.GetFloat("_MaxVal"); EditorGUILayout.MinMaxSlider("Visible value range", ref minVal, ref maxVal, 0.0f, 1.0f); mat.SetFloat("_MinVal", minVal); mat.SetFloat("_MaxVal", maxVal); } if (newRenderMode != oldRenderMode) { volrendObj.SetRenderMode(newRenderMode); } }
public static void ImportDataset(string filePath) { DatasetType datasetType = DatasetImporterUtility.GetDatasetType(filePath); switch (datasetType) { case DatasetType.Raw: { RAWDatasetImporterEditorWindow wnd = (RAWDatasetImporterEditorWindow)EditorWindow.GetWindow(typeof(RAWDatasetImporterEditorWindow)); if (wnd != null) { wnd.Close(); } wnd = new RAWDatasetImporterEditorWindow(filePath); wnd.Show(); break; } case DatasetType.DICOM: { string directoryPath = new FileInfo(filePath).Directory.FullName; // Find all DICOM files in directory IEnumerable <string> fileCandidates = Directory.EnumerateFiles(directoryPath, "*.*", SearchOption.TopDirectoryOnly) .Where(p => p.EndsWith(".dcm", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicom", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicm", StringComparison.InvariantCultureIgnoreCase)); DatasetImporterBase importer = new DICOMImporter(fileCandidates, Path.GetFileName(directoryPath)); VolumeDataset dataset = importer.Import(); if (dataset != null) { VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); } break; } } }
private void ImportDataset() { DatasetImporterBase importer = null; switch (datasetType) { case DatasetType.Raw: { importer = new RawDatasetImporter(fileToImport, dimX, dimY, dimZ, dataFormat, bytesToSkip); break; } case DatasetType.DICOM: { importer = new DICOMImporter(new FileInfo(fileToImport).Directory.FullName, false); break; } } VolumeDataset dataset = null; if (importer != null) { dataset = importer.Import(); } if (dataset != null) { VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); } else { Debug.LogError("Failed to import datset"); } this.Close(); }
private void ImportDataset() { RawDatasetImporter importer = new RawDatasetImporter(fileToImport, dimX, dimY, dimZ, dataFormat, endianness, bytesToSkip); VolumeDataset dataset = importer.Import(); if (dataset != null) { if (EditorPrefs.GetBool("DownscaleDatasetPrompt")) { if (EditorUtility.DisplayDialog("Optional DownScaling", $"Do you want to downscale the dataset? The dataset's dimension is: {dataset.dimX} x {dataset.dimY} x {dataset.dimZ}", "Yes", "No")) { dataset.DownScaleData(); } } VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); } else { Debug.LogError("Failed to import datset"); } this.Close(); }
public static VolumeRenderedObject CreateObject(VolumeDataset dataset) { GameObject obj = GameObject.Instantiate((GameObject)Resources.Load("VolumeRenderedObject")); VolumeRenderedObject volObj = obj.GetComponent <VolumeRenderedObject>(); MeshRenderer meshRenderer = obj.GetComponent <MeshRenderer>(); meshRenderer.material = new Material(meshRenderer.sharedMaterial); volObj.dataset = dataset; const int noiseDimX = 512; const int noiseDimY = 512; Texture2D noiseTexture = NoiseTextureGenerator.GenerateNoiseTexture(noiseDimX, noiseDimY); TransferFunction tf = TransferFunctionDatabase.CreateTransferFunction(); Texture2D tfTexture = tf.GetTexture(); volObj.transferFunction = tf; tf.histogramTexture = HistogramTextureGenerator.GenerateHistogramTexture(dataset); TransferFunction2D tf2D = TransferFunctionDatabase.CreateTransferFunction2D(); volObj.transferFunction2D = tf2D; meshRenderer.sharedMaterial.SetTexture("_DataTex", dataset.GetDataTexture()); meshRenderer.sharedMaterial.SetTexture("_GradientTex", null); meshRenderer.sharedMaterial.SetTexture("_NoiseTex", noiseTexture); meshRenderer.sharedMaterial.SetTexture("_TFTex", tfTexture); meshRenderer.sharedMaterial.EnableKeyword("MODE_DVR"); meshRenderer.sharedMaterial.DisableKeyword("MODE_MIP"); meshRenderer.sharedMaterial.DisableKeyword("MODE_SURF"); return(volObj); }
private void ImportDataset() { DatasetImporterBase importer = null; switch (datasetType) { case DatasetType.Raw: { importer = new RawDatasetImporter(fileToImport, dimX, dimY, dimZ, dataFormat, bytesToSkip); break; } case DatasetType.DICOM: { throw new System.NotImplementedException("TODO: implement support for DICOM files"); } } VolumeDataset dataset = null; if (importer != null) { dataset = importer.Import(); } if (dataset != null) { VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); } else { Debug.LogError("Failed to import datset"); } this.Close(); }
private void OnGUI() { // Update selected object if (volRendObject == null) { volRendObject = SelectionHelper.GetSelectedVolumeObject(); } if (volRendObject == null) { return; } tf = volRendObject.transferFunction; Event currentEvent = new Event(Event.current); Color oldColour = GUI.color; // Used for setting GUI.color when drawing UI elements float contentWidth = Mathf.Min(this.position.width, (this.position.height - 100.0f) * 2.0f); float contentHeight = contentWidth * 0.5f; // Interaction area (slightly larger than the histogram rect) Rect interactRect = new Rect(0.0f, 0.0f, contentWidth, contentHeight); // Histogram rect (histogram view and alpha control points) Rect histRect = new Rect(interactRect.x + 20.0f, interactRect.y + 20.0f, interactRect.width - 40.0f, interactRect.height - 40.0f); // Colour palette rect (colour control points) Rect paletteRect = new Rect(histRect.x, histRect.y + histRect.height + 20, histRect.width, 20.0f); // TODO: Don't do this every frame tf.GenerateTexture(); // Create histogram texture if (histTex == null) { if (SystemInfo.supportsComputeShaders) { histTex = HistogramTextureGenerator.GenerateHistogramTextureOnGPU(volRendObject.dataset); } else { histTex = HistogramTextureGenerator.GenerateHistogramTexture(volRendObject.dataset); } } // Draw histogram tfGUIMat.SetTexture("_TFTex", tf.GetTexture()); tfGUIMat.SetTexture("_HistTex", histTex); Graphics.DrawTexture(histRect, tf.GetTexture(), tfGUIMat); // Draw colour palette Texture2D tfTexture = tf.GetTexture(); tfPaletteGUIMat.SetTexture("_TFTex", tf.GetTexture()); Graphics.DrawTexture(new Rect(paletteRect.x, paletteRect.y, paletteRect.width, paletteRect.height), tfTexture, tfPaletteGUIMat); // Release selected colour/alpha points if mouse leaves window if (movingAlphaPointIndex != -1 && !interactRect.Contains(currentEvent.mousePosition)) { movingAlphaPointIndex = -1; } if (movingColPointIndex != -1 && !(currentEvent.mousePosition.x >= paletteRect.x && currentEvent.mousePosition.x <= paletteRect.x + paletteRect.width)) { movingColPointIndex = -1; } // Mouse down => Move or remove selected colour control point if (currentEvent.type == EventType.MouseDown && paletteRect.Contains(currentEvent.mousePosition)) { float mousePos = (currentEvent.mousePosition.x - paletteRect.x) / paletteRect.width; int pointIndex = PickColourControlPoint(mousePos); if (pointIndex != -1) { // Add control point if (currentEvent.button == 0 && !currentEvent.control) { movingColPointIndex = selectedColPointIndex = pointIndex; } // Remove control point else if (currentEvent.button == 1 && currentEvent.control) { tf.colourControlPoints.RemoveAt(pointIndex); currentEvent.type = EventType.Ignore; movingColPointIndex = selectedColPointIndex = -1; } } } else if (currentEvent.type == EventType.MouseUp) { movingColPointIndex = -1; } // Mouse down => Move or remove selected alpha control point if (currentEvent.type == EventType.MouseDown) { Vector2 mousePos = new Vector2((currentEvent.mousePosition.x - histRect.x) / histRect.width, 1.0f - (currentEvent.mousePosition.y - histRect.y) / histRect.height); int pointIndex = PickAlphaControlPoint(mousePos); if (pointIndex != -1) { // Add control point if (currentEvent.button == 0 && !currentEvent.control) { movingAlphaPointIndex = pointIndex; } // Remove control point else if (currentEvent.button == 1 && currentEvent.control) { tf.alphaControlPoints.RemoveAt(pointIndex); currentEvent.type = EventType.Ignore; selectedColPointIndex = -1; } } } // Move selected alpha control point if (movingAlphaPointIndex != -1) { TFAlphaControlPoint alphaPoint = tf.alphaControlPoints[movingAlphaPointIndex]; alphaPoint.dataValue = Mathf.Clamp((currentEvent.mousePosition.x - histRect.x) / histRect.width, 0.0f, 1.0f); alphaPoint.alphaValue = Mathf.Clamp(1.0f - (currentEvent.mousePosition.y - histRect.y) / histRect.height, 0.0f, 1.0f); tf.alphaControlPoints[movingAlphaPointIndex] = alphaPoint; } // Move selected colour control point if (movingColPointIndex != -1) { TFColourControlPoint colPoint = tf.colourControlPoints[movingColPointIndex]; colPoint.dataValue = Mathf.Clamp((currentEvent.mousePosition.x - paletteRect.x) / paletteRect.width, 0.0f, 1.0f); tf.colourControlPoints[movingColPointIndex] = colPoint; } // Draw colour control points for (int iCol = 0; iCol < tf.colourControlPoints.Count; iCol++) { TFColourControlPoint colPoint = tf.colourControlPoints[iCol]; Rect ctrlBox = new Rect(histRect.x + histRect.width * colPoint.dataValue, histRect.y + histRect.height + 20, 10, 20); GUI.color = Color.red; GUI.skin.box.fontSize = 6; GUI.Box(ctrlBox, "*"); } // Draw alpha control points for (int iAlpha = 0; iAlpha < tf.alphaControlPoints.Count; iAlpha++) { const int pointSize = 10; TFAlphaControlPoint alphaPoint = tf.alphaControlPoints[iAlpha]; Rect ctrlBox = new Rect(histRect.x + histRect.width * alphaPoint.dataValue - pointSize / 2, histRect.y + (1.0f - alphaPoint.alphaValue) * histRect.height - pointSize / 2, pointSize, pointSize); GUI.color = Color.red; GUI.skin.box.fontSize = 6; GUI.Box(ctrlBox, "*"); GUI.color = oldColour; } if (currentEvent.type == EventType.MouseUp) { movingColPointIndex = -1; movingAlphaPointIndex = -1; } // Add points if (currentEvent.type == EventType.MouseDown && currentEvent.button == 1) { if (histRect.Contains(new Vector2(currentEvent.mousePosition.x, currentEvent.mousePosition.y))) { tf.alphaControlPoints.Add(new TFAlphaControlPoint(Mathf.Clamp((currentEvent.mousePosition.x - histRect.x) / histRect.width, 0.0f, 1.0f), Mathf.Clamp(1.0f - (currentEvent.mousePosition.y - histRect.y) / histRect.height, 0.0f, 1.0f))); } else { tf.colourControlPoints.Add(new TFColourControlPoint(Mathf.Clamp((currentEvent.mousePosition.x - histRect.x) / histRect.width, 0.0f, 1.0f), Random.ColorHSV())); } selectedColPointIndex = -1; } // Save TF if (GUI.Button(new Rect(histRect.x, histRect.y + histRect.height + 50.0f, 70.0f, 30.0f), "Save")) { string filepath = EditorUtility.SaveFilePanel("Save transfer function", "", "default.tf", "tf"); if (filepath != "") { TransferFunctionDatabase.SaveTransferFunction(tf, filepath); } } // Load TF if (GUI.Button(new Rect(histRect.x + 75.0f, histRect.y + histRect.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; } } } // Clear TF if (GUI.Button(new Rect(histRect.x + 150.0f, histRect.y + histRect.height + 50.0f, 70.0f, 30.0f), "Clear")) { tf = volRendObject.transferFunction = new TransferFunction(); tf.alphaControlPoints.Add(new TFAlphaControlPoint(0.2f, 0.0f)); tf.alphaControlPoints.Add(new TFAlphaControlPoint(0.8f, 1.0f)); tf.colourControlPoints.Add(new TFColourControlPoint(0.5f, new Color(0.469f, 0.354f, 0.223f, 1.0f))); selectedColPointIndex = -1; } // Colour picker if (selectedColPointIndex != -1) { TFColourControlPoint colPoint = tf.colourControlPoints[selectedColPointIndex]; colPoint.colourValue = EditorGUI.ColorField(new Rect(histRect.x + 225, histRect.y + histRect.height + 50, 100.0f, 40.0f), colPoint.colourValue); tf.colourControlPoints[selectedColPointIndex] = colPoint; } GUI.skin.label.wordWrap = false; GUI.Label(new Rect(histRect.x, histRect.y + histRect.height + 85.0f, 720.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."); GUI.color = oldColour; }
private void OnGUI() { // Update selected object if (volRendObject == null) { volRendObject = SelectionHelper.GetSelectedVolumeObject(); } if (volRendObject == null) { return; } tf = volRendObject.transferFunction; Event currentEvent = new Event(Event.current); Color oldColour = GUI.color; 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(); if (histTex == null) { histTex = HistogramTextureGenerator.GenerateHistogramTexture(volRendObject.dataset); } tfGUIMat.SetTexture("_TFTex", tf.GetTexture()); tfGUIMat.SetTexture("_HistTex", histTex); Graphics.DrawTexture(bgRect, tf.GetTexture(), tfGUIMat); Texture2D tfTexture = tf.GetTexture(); tfPaletteGUIMat.SetTexture("_TFTex", tf.GetTexture()); Graphics.DrawTexture(new Rect(bgRect.x, bgRect.y + bgRect.height + 20, bgRect.width, 20.0f), tfTexture, tfPaletteGUIMat); // Colour control points for (int iCol = 0; iCol < tf.colourControlPoints.Count; iCol++) { TFColourControlPoint colPoint = tf.colourControlPoints[iCol]; Rect ctrlBox = new Rect(bgRect.x + bgRect.width * colPoint.dataValue, bgRect.y + bgRect.height + 20, 10, 20); GUI.color = Color.red; GUI.skin.box.fontSize = 6; GUI.Box(ctrlBox, "*"); if (currentEvent.type == EventType.MouseDown && ctrlBox.Contains(new Vector2(currentEvent.mousePosition.x, currentEvent.mousePosition.y))) { // Move colour control point if (currentEvent.button == 0) { movingColPointIndex = iCol; selectedColPointIndex = iCol; } // Remove it (if ctrl + right click) else if (currentEvent.button == 1 && currentEvent.control) { tf.colourControlPoints.RemoveAt(iCol); currentEvent.type = EventType.Ignore; selectedColPointIndex = -1; continue; } } else if (movingColPointIndex == iCol) { colPoint.dataValue = Mathf.Clamp((currentEvent.mousePosition.x - bgRect.x) / bgRect.width, 0.0f, 1.0f); } tf.colourControlPoints[iCol] = colPoint; } // Alpha control points for (int iAlpha = 0; iAlpha < tf.alphaControlPoints.Count; iAlpha++) { TFAlphaControlPoint alphaPoint = tf.alphaControlPoints[iAlpha]; Rect ctrlBox = new Rect(bgRect.x + bgRect.width * alphaPoint.dataValue, bgRect.y + (1.0f - alphaPoint.alphaValue) * bgRect.height, 10, 10); GUI.color = oldColour; GUI.skin.box.fontSize = 6; GUI.Box(ctrlBox, "*"); if (currentEvent.type == EventType.MouseDown && ctrlBox.Contains(new Vector2(currentEvent.mousePosition.x, currentEvent.mousePosition.y))) { // Move alpha point if (currentEvent.button == 0) { movingAlphaPointIndex = iAlpha; } // Remove alpha point else if (currentEvent.button == 1 && currentEvent.control) { tf.alphaControlPoints.RemoveAt(iAlpha); currentEvent.type = EventType.Ignore; selectedColPointIndex = -1; continue; } } else if (movingAlphaPointIndex == iAlpha) { alphaPoint.dataValue = Mathf.Clamp((currentEvent.mousePosition.x - bgRect.x) / bgRect.width, 0.0f, 1.0f); alphaPoint.alphaValue = Mathf.Clamp(1.0f - (currentEvent.mousePosition.y - bgRect.y) / bgRect.height, 0.0f, 1.0f); } tf.alphaControlPoints[iAlpha] = alphaPoint; } if (currentEvent.type == EventType.MouseUp) { movingColPointIndex = -1; movingAlphaPointIndex = -1; } // Add points if (currentEvent.type == EventType.MouseDown && currentEvent.button == 1) { if (bgRect.Contains(new Vector2(currentEvent.mousePosition.x, currentEvent.mousePosition.y))) { tf.alphaControlPoints.Add(new TFAlphaControlPoint(Mathf.Clamp((currentEvent.mousePosition.x - bgRect.x) / bgRect.width, 0.0f, 1.0f), Mathf.Clamp(1.0f - (currentEvent.mousePosition.y - bgRect.y) / bgRect.height, 0.0f, 1.0f))); } else { tf.colourControlPoints.Add(new TFColourControlPoint(Mathf.Clamp((currentEvent.mousePosition.x - bgRect.x) / bgRect.width, 0.0f, 1.0f), Random.ColorHSV())); } selectedColPointIndex = -1; } if (selectedColPointIndex != -1) { TFColourControlPoint colPoint = tf.colourControlPoints[selectedColPointIndex]; colPoint.colourValue = EditorGUI.ColorField(new Rect(150, bgRect.y + bgRect.height + 50, 100.0f, 40.0f), colPoint.colourValue); tf.colourControlPoints[selectedColPointIndex] = colPoint; } 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."); GUI.color = oldColour; }
private void OnGUI() { // Update selected object if (volRendObject == null) { volRendObject = SelectionHelper.GetSelectedVolumeObject(); } if (volRendObject == null) { return; } if (hist2DTex == null) { hist2DTex = HistogramTextureGenerator.Generate2DHistogramTexture(volRendObject.dataset); } TransferFunction2D tf2d = volRendObject.transferFunction2D; // Calculate GUI width (minimum of window width and window height * 2) float bgWidth = Mathf.Min(this.position.width - 20.0f, (this.position.height - 250.0f) * 2.0f); // Draw the histogram Rect histRect = new Rect(0.0f, 0.0f, bgWidth, bgWidth * 0.5f); Graphics.DrawTexture(histRect, hist2DTex); // Draw the TF texture (showing the rectangles) tfGUIMat.SetTexture("_TFTex", tf2d.GetTexture()); Graphics.DrawTexture(histRect, tf2d.GetTexture(), tfGUIMat); // Handle mouse click in box for (int iBox = 0; iBox < tf2d.boxes.Count; iBox++) { TransferFunction2D.TF2DBox box = tf2d.boxes[iBox]; Rect boxRect = new Rect(histRect.x + box.rect.x * histRect.width, histRect.y + (1.0f - box.rect.height - box.rect.y) * histRect.height, box.rect.width * histRect.width, box.rect.height * histRect.height); if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && boxRect.Contains(new Vector2(Event.current.mousePosition.x, Event.current.mousePosition.y))) { selectedBoxIndex = iBox; } } float startX = histRect.x; float startY = histRect.y + histRect.height + 10; // Show GUI for editing selected rectangle if (selectedBoxIndex != -1) { EditorGUI.BeginChangeCheck(); TransferFunction2D.TF2DBox box = tf2d.boxes[selectedBoxIndex]; float oldX = box.rect.x; float oldY = box.rect.y; box.rect.x = EditorGUI.Slider(new Rect(startX, startY, 200.0f, 20.0f), "x", box.rect.x, 0.0f, 0.99f); box.rect.width = EditorGUI.Slider(new Rect(startX + 220.0f, startY, 200.0f, 20.0f), "width", oldX + box.rect.width, box.rect.x + 0.01f, 1.0f) - box.rect.x; box.rect.y = EditorGUI.Slider(new Rect(startX, startY + 50, 200.0f, 20.0f), "y", box.rect.y, 0.0f, 1.0f); box.rect.height = EditorGUI.Slider(new Rect(startX + 220.0f, startY + 50, 200.0f, 20.0f), "height", oldY + box.rect.height, box.rect.y + 0.01f, 1.0f) - box.rect.y; box.colour = EditorGUI.ColorField(new Rect(startX + 450.0f, startY + 10, 100.0f, 20.0f), box.colour); box.minAlpha = EditorGUI.Slider(new Rect(startX + 450.0f, startY + 30, 200.0f, 20.0f), "min alpha", box.minAlpha, 0.0f, 1.0f); box.alpha = EditorGUI.Slider(new Rect(startX + 450.0f, startY + 60, 200.0f, 20.0f), "max alpha", box.alpha, 0.0f, 1.0f); tf2d.boxes[selectedBoxIndex] = box; needsRegenTexture |= EditorGUI.EndChangeCheck(); } else { EditorGUI.LabelField(new Rect(startX, startY, this.position.width - startX, 50.0f), "Select a rectangle in the above view, or add a new one."); } // Add new 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; } // Remove selected shape if (selectedBoxIndex != -1) { 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; } volRendObject.SetTransferFunctionMode(TFRenderMode.TF2D); return; }
private void OnGUI() { SlicingPlane[] spawnedPlanes = FindObjectsOfType <SlicingPlane>(); if (spawnedPlanes.Length > 0) { selectedPlaneIndex = selectedPlaneIndex % spawnedPlanes.Length; } 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); if (selectedPlaneIndex != -1 && spawnedPlanes.Length > 0) { SlicingPlane planeObj = spawnedPlanes[System.Math.Min(selectedPlaneIndex, spawnedPlanes.Length - 1)]; // Draw the slice view Material mat = planeObj.GetComponent <MeshRenderer>().sharedMaterial; Graphics.DrawTexture(bgRect, mat.GetTexture("_DataTex"), mat); // Handle mouse click inside slice view (activates moving the plane with mouse) if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && bgRect.Contains(new Vector2(Event.current.mousePosition.x, Event.current.mousePosition.y))) { handleMouseMovement = true; prevMousePos = Event.current.mousePosition; } // Handle mouse movement (move the plane) if (handleMouseMovement) { Vector2 mouseOffset = (Event.current.mousePosition - prevMousePos) / new Vector2(bgRect.width, bgRect.height); if (Mathf.Abs(mouseOffset.y) > 0.00001f) { planeObj.transform.Translate(Vector3.up * mouseOffset.y); prevMousePos = Event.current.mousePosition; } } } if (Event.current.type == EventType.MouseUp) { handleMouseMovement = false; } // Show buttons for changing the active plane if (spawnedPlanes.Length > 0) { if (GUI.Button(new Rect(0.0f, bgRect.y + bgRect.height + 20.0f, 70.0f, 30.0f), "previous\nplane")) { selectedPlaneIndex = (selectedPlaneIndex - 1) % spawnedPlanes.Length; Selection.activeGameObject = spawnedPlanes[selectedPlaneIndex].gameObject; } if (GUI.Button(new Rect(90.0f, bgRect.y + bgRect.height + 20.0f, 70.0f, 30.0f), "next\nplane")) { selectedPlaneIndex = (selectedPlaneIndex + 1) % spawnedPlanes.Length; Selection.activeGameObject = spawnedPlanes[selectedPlaneIndex].gameObject; } } // Show button for adding new plane if (GUI.Button(new Rect(180.0f, bgRect.y + bgRect.height + 20.0f, 70.0f, 30.0f), "add\nplane")) { VolumeRenderedObject volRend = FindObjectOfType <VolumeRenderedObject>(); if (volRend != null) { selectedPlaneIndex = spawnedPlanes.Length; volRend.CreateSlicingPlane(); } } // Show button for removing if (spawnedPlanes.Length > 0 && GUI.Button(new Rect(270.0f, bgRect.y + bgRect.height + 20.0f, 70.0f, 30.0f), "remove\nplane")) { SlicingPlane planeToRemove = spawnedPlanes[selectedPlaneIndex]; GameObject.DestroyImmediate(planeToRemove.gameObject); } // Show hint if (spawnedPlanes.Length > 0) { GUI.Label(new Rect(0.0f, bgRect.y + bgRect.height + 60.0f, 450.0f, 30.0f), "Move plane by left clicking in the above view and dragging the mouse,\n or simply move it in the object hierarchy."); } }
public static void ImportDataset(string filePath) { DatasetType datasetType = DatasetImporterUtility.GetDatasetType(filePath); switch (datasetType) { case DatasetType.Raw: { RAWDatasetImporterEditorWindow wnd = (RAWDatasetImporterEditorWindow)EditorWindow.GetWindow(typeof(RAWDatasetImporterEditorWindow)); if (wnd != null) { wnd.Close(); } wnd = new RAWDatasetImporterEditorWindow(filePath); wnd.Show(); break; } case DatasetType.DICOM: { string directoryPath = new FileInfo(filePath).Directory.FullName; // Find all DICOM files in directory IEnumerable <string> fileCandidates = Directory.EnumerateFiles(directoryPath, "*.*", SearchOption.TopDirectoryOnly) .Where(p => p.EndsWith(".dcm", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicom", StringComparison.InvariantCultureIgnoreCase) || p.EndsWith(".dicm", StringComparison.InvariantCultureIgnoreCase)); DICOMImporter importer = new DICOMImporter(fileCandidates, Path.GetFileName(directoryPath)); List <DICOMImporter.DICOMSeries> seriesList = importer.LoadDICOMSeries(); foreach (DICOMImporter.DICOMSeries series in seriesList) { // Only import the series that contains the selected file if (series.dicomFiles.Any(f => Path.GetFileName(f.filePath) == Path.GetFileName(filePath))) { VolumeDataset dataset = importer.ImportDICOMSeries(series); if (dataset != null) { VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); } } } break; } case DatasetType.PARCHG: { ParDatasetImporter importer = new ParDatasetImporter(filePath); VolumeDataset dataset = importer.Import(); if (dataset != null) { VolumeRenderedObject obj = VolumeObjectFactory.CreateObject(dataset); } else { Debug.LogError("Failed to import datset"); } break; } } }