private void ImportDataset() { DatasetImporterBase importer = null; switch (datasetType) { case DatasetType.Raw: { importer = new RawDatasetImporter(fileToImport, dimX, dimY, dimZ, DataContentFormat.Int16, 6); 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 VolumeRenderedObject Import(string dir) { 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()) { DICOMImporter importer = new DICOMImporter(fileCandidates, Path.GetFileName(dir)); VolumeDataset dataset = importer.Import(); if (dataset != null) { VolumeRenderedObject vo = VolumeObjectFactory.CreateObject(dataset); vo.transform.Rotate(new Vector3(180, 0, 0)); return(vo); } } else { Debug.LogError("Could not find any DICOM files to import."); } } return(null); }
public override void OnInspectorGUI() { VolumeRenderedObject myTarget = (VolumeRenderedObject)target; RenderMode oldRenderMode = myTarget.GetRemderMode(); RenderMode newRenderMode = (RenderMode)EditorGUILayout.EnumPopup("Render mode", oldRenderMode); if (newRenderMode != oldRenderMode) { myTarget.SetRenderMode(newRenderMode); } }
private void UpdateBrain(VolumeRenderedObject vro) { if (vro != null) { /* update renderer and bounds */ // volume data is stored in child gameobject rend = vro.transform.GetChild(0).GetComponent <Renderer>(); Vector3 center = rend.bounds.center; float radius = rend.bounds.extents.magnitude; float x = rend.bounds.extents.x; float y = rend.bounds.extents.y; float z = rend.bounds.extents.z; // update position so that the world origin point is at the corner of brain vro.transform.position = new Vector3(x, y, z); } }
private void ImportDataset() { DatasetImporterBase importer = null; switch (datasetType) { case DatasetType.Raw: { importer = new RawDatasetImporter(fileToImport, dimX, dimY, dimZ, DataContentFormat.Int16, 6); 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() { 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, 100.0f, 30.0f), "previous\nplane")) { selectedPlaneIndex = (selectedPlaneIndex - 1) % spawnedPlanes.Length; Selection.activeGameObject = spawnedPlanes[selectedPlaneIndex].gameObject; } if (GUI.Button(new Rect(120.0f, bgRect.y + bgRect.height + 20.0f, 100.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(240.0f, bgRect.y + bgRect.height + 20.0f, 100.0f, 30.0f), "add\nplane")) { VolumeRenderedObject volRend = FindObjectOfType <VolumeRenderedObject>(); if (volRend != null) { selectedPlaneIndex = spawnedPlanes.Length; volRend.CreateSlicingPlane(); } } // 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."); } }
private void OnGUI() { VolumeRenderedObject volRend = FindObjectOfType <VolumeRenderedObject>(); if (volRend == null) { return; } tf = volRend.transferFunction; 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); tf.GenerateTexture(); histogramMaterial.SetTexture("_TFTex", tf.GetTexture()); histogramMaterial.SetTexture("_HistTex", tf.histogramTexture); Graphics.DrawTexture(bgRect, tf.GetTexture(), histogramMaterial); Texture2D tfTexture = tf.GetTexture(); colorBarMaterial.SetTexture("_TFTex", tf.GetTexture()); Graphics.DrawTexture(new Rect(bgRect.x, bgRect.y + bgRect.height + 20, bgRect.width, 20.0f), tfTexture, colorBarMaterial); // Colour control points for (int iCol = 0; iCol < tf.colourControlPoints.Count; iCol++) { ControlPointColor 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 = 8; GUI.Box(ctrlBox, "|"); if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && ctrlBox.Contains(new Vector2(Event.current.mousePosition.x, Event.current.mousePosition.y))) { movingColPointIndex = iCol; selectedColPointIndex = iCol; } else if (movingColPointIndex == iCol) { colPoint.dataValue = Mathf.Clamp((Event.current.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++) { ControlPointAlpha 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, "a"); if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && ctrlBox.Contains(new Vector2(Event.current.mousePosition.x, Event.current.mousePosition.y))) { movingAlphaPointIndex = iAlpha; } else if (movingAlphaPointIndex == iAlpha) { alphaPoint.dataValue = Mathf.Clamp((Event.current.mousePosition.x - bgRect.x) / bgRect.width, 0.0f, 1.0f); alphaPoint.alphaValue = Mathf.Clamp(1.0f - (Event.current.mousePosition.y - bgRect.y) / bgRect.height, 0.0f, 1.0f); } tf.alphaControlPoints[iAlpha] = alphaPoint; } if (Event.current.type == EventType.MouseUp) { movingColPointIndex = -1; movingAlphaPointIndex = -1; } if (Event.current.type == EventType.MouseDown && Event.current.button == 1) { if (bgRect.Contains(new Vector2(Event.current.mousePosition.x, Event.current.mousePosition.y))) { tf.alphaControlPoints.Add( tf.CreateControlPointAlpha( Mathf.Clamp((Event.current.mousePosition.x - bgRect.x) / bgRect.width, 0.0f, 1.0f), Mathf.Clamp(1.0f - (Event.current.mousePosition.y - bgRect.y) / bgRect.height, 0.0f, 1.0f) )); } else { tf.colourControlPoints.Add(tf.CreateControlPointColor(Mathf.Clamp((Event.current.mousePosition.x - bgRect.x) / bgRect.width, 0.0f, 1.0f), Random.ColorHSV())); } selectedColPointIndex = -1; } if (selectedColPointIndex != -1) { ControlPointColor colPoint = tf.colourControlPoints[selectedColPointIndex]; colPoint.colourValue = EditorGUI.ColorField(new Rect(bgRect.x, bgRect.y + bgRect.height + 50, 100.0f, 40.0f), colPoint.colourValue); tf.colourControlPoints[selectedColPointIndex] = colPoint; } // TEST!!! TODO volRend.GetComponent <MeshRenderer>().sharedMaterial.SetTexture("_TFTex", tfTexture); volRend.GetComponent <MeshRenderer>().sharedMaterial.DisableKeyword("TF2D_ON"); GUI.color = oldColour; }
public void OnSegmentationButtonClicked() { brainSeg = Import(completePath + "_seg"); brainSeg.transform.GetChild(0).GetComponent <Renderer>().material = matBrainSeg; UpdateBrain(brainSeg); }
public void OnImportButtonClicked() { brain = Import(completePath + "_flair"); UpdateBrain(brain); }
public VolumeRenderedObject CreateVolumeRenderedObject(VolumeDataset dataset) { GameObject go = GameObject.Instantiate(volumeObjectPrefab) as GameObject; go.transform.SetParent(Program.instance.operationOverlay.transform); go.transform.localPosition = new Vector3(-0.0083f, 0.0426f, 0.0083f); go.transform.rotation = Quaternion.Euler(-20f, 180f, 180f); VolumeRenderedObject volObj = go.GetComponent <VolumeRenderedObject>(); MeshRenderer meshRenderer = go.GetComponent <MeshRenderer>(); volObj.dataset = dataset; int dimX = dataset.dimX; int dimY = dataset.dimY; int dimZ = dataset.dimZ; int maxRange = dataset.maxDataValue - dataset.minDataValue; Color[] cols = new Color[dataset.data.Length]; for (int x = 0; x < dataset.dimX; x++) { for (int y = 0; y < dataset.dimY; y++) { for (int z = 0; z < dataset.dimZ; z++) { int iData = x + y * dimX + z * (dimX * dimY); int x1 = dataset.data[Mathf.Min(x + 1, dimX - 1) + y * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; int x2 = dataset.data[Mathf.Max(x - 1, 0) + y * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; int y1 = dataset.data[x + Mathf.Min(y + 1, dimY - 1) * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; int y2 = dataset.data[x + Mathf.Max(y - 1, 0) * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; int z1 = dataset.data[x + y * dataset.dimX + Mathf.Min(z + 1, dimZ - 1) * (dataset.dimX * dataset.dimY)]; int z2 = dataset.data[x + y * dataset.dimX + Mathf.Max(z - 1, 0) * (dataset.dimX * dataset.dimY)]; Vector3 grad = new Vector3((x2 - x1) / (float)maxRange, (y2 - y1) / (float)maxRange, (z2 - z1) / (float)maxRange); cols[iData] = new Color(grad.x, grad.y, grad.z, (float)dataset.data[iData] / (float)dataset.maxDataValue); } } } dataset.texture.SetPixels(cols); dataset.texture.Apply(); Texture3D tex = dataset.texture; const int noiseDimX = 512; const int noiseDimY = 512; Texture2D noiseTexture = NoiseTextureGenerator.GenerateNoiseTexture(noiseDimX, noiseDimY); TransferFunction tf = Program.instance.transferFunctionManager.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); volObj.transferFunction2D = tf2D; meshRenderer.sharedMaterial.SetTexture("_DataTex", tex); 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); }
public static VolumeRenderedObject CreateObject(VolumeDataset dataset) { GameObject obj = GameObject.Instantiate((GameObject)Resources.Load("VolumeRenderedObject")); VolumeRenderedObject volObj = obj.GetComponent <VolumeRenderedObject>(); MeshRenderer meshRenderer = obj.GetComponent <MeshRenderer>(); volObj.dataset = dataset; int dimX = dataset.dimX; int dimY = dataset.dimY; int dimZ = dataset.dimZ; int maxRange = dataset.maxDataValue - dataset.minDataValue; Color[] cols = new Color[dataset.data.Length]; for (int x = 0; x < dataset.dimX; x++) { for (int y = 0; y < dataset.dimY; y++) { for (int z = 0; z < dataset.dimZ; z++) { int iData = x + y * dimX + z * (dimX * dimY); int x1 = dataset.data[Math.Min(x + 1, dimX - 1) + y * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; int x2 = dataset.data[Math.Max(x - 1, 0) + y * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; int y1 = dataset.data[x + Math.Min(y + 1, dimY - 1) * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; int y2 = dataset.data[x + Math.Max(y - 1, 0) * dataset.dimX + z * (dataset.dimX * dataset.dimY)]; int z1 = dataset.data[x + y * dataset.dimX + Math.Min(z + 1, dimZ - 1) * (dataset.dimX * dataset.dimY)]; int z2 = dataset.data[x + y * dataset.dimX + Math.Max(z - 1, 0) * (dataset.dimX * dataset.dimY)]; Vector3 grad = new Vector3((x2 - x1) / (float)maxRange, (y2 - y1) / (float)maxRange, (z2 - z1) / (float)maxRange); cols[iData] = new Color(grad.x, grad.y, grad.z, (float)dataset.data[iData] / (float)dataset.maxDataValue); } } } dataset.texture.SetPixels(cols); dataset.texture.Apply(); Texture3D tex = dataset.texture; const int noiseDimX = 512; 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(); 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); volObj.transferFunction2D = tf2D; meshRenderer.sharedMaterial.SetTexture("_DataTex", tex); 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 OnGUI() { VolumeRenderedObject volRend = FindObjectOfType <VolumeRenderedObject>(); if (volRend == null) { return; } if (hist2DTex == null) { hist2DTex = HistogramTextureGenerator.Generate2DHistogramTexture(volRend.dataset); } TransferFunction2D tf2d = volRend.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, 150.0f, 40.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 + 150, 150.0f, 40.0f), "Remove selected shape")) { tf2d.boxes.RemoveAt(selectedBoxIndex); needsRegenTexture = true; } } // TODO: regenerate on add/remove/modify (and do it async) if (needsRegenTexture) { tf2d.GenerateTexture(); needsRegenTexture = false; } volRend.GetComponent <MeshRenderer>().sharedMaterial.SetTexture("_TFTex", tf2d.GetTexture()); volRend.GetComponent <MeshRenderer>().sharedMaterial.EnableKeyword("TF2D_ON"); return; }