Beispiel #1
0
        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);
        }
Beispiel #4
0
        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();
            }
        }
Beispiel #6
0
        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
        }
Beispiel #13
0
        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);
        }
Beispiel #15
0
        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);
            }
        }
Beispiel #18
0
        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;
            }
            }
        }
Beispiel #19
0
        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();
        }
Beispiel #21
0
        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();
        }
Beispiel #23
0
        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;
        }
Beispiel #25
0
        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;
        }
Beispiel #26
0
        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;
            }
            }
        }