- Added an importer to the editor.
- Cleaned up the project structure and object hierarchy.
This commit is contained in:
Родитель
da4f5453fc
Коммит
c89a894536
|
@ -0,0 +1,96 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
|
||||
public class DatasetImporterEditorWindow : EditorWindow
|
||||
{
|
||||
private enum DatasetType
|
||||
{
|
||||
Unknown,
|
||||
Raw,
|
||||
DICOM
|
||||
}
|
||||
|
||||
private string fileToImport;
|
||||
private DatasetType datasetType;
|
||||
|
||||
private int dimX; // TODO: set good default value
|
||||
private int dimY; // TODO: set good default value
|
||||
private int dimZ; // TODO: set good default value
|
||||
private int bytesToSkip = 0;
|
||||
private DataContentFormat dataFormat = DataContentFormat.Int16;
|
||||
|
||||
public DatasetImporterEditorWindow(string fileToImport)
|
||||
{
|
||||
this.fileToImport = fileToImport;
|
||||
string extension = Path.GetExtension(fileToImport);
|
||||
if (extension == ".dat" || extension == ".raw")
|
||||
datasetType = DatasetType.Raw;
|
||||
else
|
||||
datasetType = DatasetType.Unknown;
|
||||
|
||||
if(extension == ".dat")
|
||||
{
|
||||
FileStream fs = new FileStream(fileToImport, FileMode.Open);
|
||||
BinaryReader reader = new BinaryReader(fs);
|
||||
|
||||
dimX = reader.ReadUInt16();
|
||||
dimY = reader.ReadUInt16();
|
||||
dimZ = reader.ReadUInt16();
|
||||
bytesToSkip = 6;
|
||||
|
||||
reader.Close();
|
||||
fs.Close();
|
||||
}
|
||||
}
|
||||
|
||||
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 void OnGUI()
|
||||
{
|
||||
switch(datasetType)
|
||||
{
|
||||
case DatasetType.Raw:
|
||||
{
|
||||
dimX = EditorGUILayout.IntField("X dimension", dimX);
|
||||
dimY = EditorGUILayout.IntField("X dimension", dimY);
|
||||
dimZ = EditorGUILayout.IntField("X dimension", dimZ);
|
||||
bytesToSkip = EditorGUILayout.IntField("Bytes to skip", bytesToSkip);
|
||||
dataFormat = (DataContentFormat)EditorGUILayout.EnumPopup("Data format", dataFormat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(GUILayout.Button("Import"))
|
||||
ImportDataset();
|
||||
|
||||
if (GUILayout.Button("Cancel"))
|
||||
this.Close();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a00a6dc9906286a46948a51d4f7c56ab
|
||||
guid: a6938a09f67b77c4b9e832cf63203399
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
|
@ -14,9 +14,6 @@ public class SliceRenderingEditorWindow : EditorWindow
|
|||
|
||||
private void OnGUI()
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
return;
|
||||
|
||||
SlicingPlane[] spawnedPlanes = FindObjectsOfType<SlicingPlane>();
|
||||
|
||||
if(spawnedPlanes.Length > 0)
|
||||
|
@ -41,7 +38,7 @@ public class SliceRenderingEditorWindow : EditorWindow
|
|||
}
|
||||
if (GUI.Button(new Rect(240.0f, bgRect.y + bgRect.height + 20.0f, 100.0f, 100.0f), "+"))
|
||||
{
|
||||
VolumeRenderer volRend = FindObjectOfType<VolumeRenderer>();
|
||||
VolumeRenderedObject volRend = FindObjectOfType<VolumeRenderedObject>();
|
||||
if(volRend != null)
|
||||
{
|
||||
selectedPlaneIndex = spawnedPlanes.Length;
|
||||
|
|
|
@ -28,17 +28,14 @@ public class TransferFunction2DEditorWindow : EditorWindow
|
|||
|
||||
private void OnGUI()
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
return;
|
||||
|
||||
VolumeRenderer volRend = FindObjectOfType<VolumeRenderer>();
|
||||
VolumeRenderedObject volRend = FindObjectOfType<VolumeRenderedObject>();
|
||||
if (volRend == null)
|
||||
return;
|
||||
|
||||
if (hist2DTex == null)
|
||||
hist2DTex = HistogramTextureGenerator.Generate2DHistogramTexture(volRend.volumeDataset);
|
||||
hist2DTex = HistogramTextureGenerator.Generate2DHistogramTexture(volRend.dataset);
|
||||
|
||||
TransferFunction2D tf2d = volRend.tf2D;
|
||||
TransferFunction2D tf2d = volRend.transferFunction2D;
|
||||
|
||||
//tf.GenerateTexture();
|
||||
|
||||
|
|
|
@ -32,13 +32,10 @@ public class TransferFunctionEditorWindow : EditorWindow
|
|||
|
||||
private void OnGUI()
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
return;
|
||||
|
||||
VolumeRenderer volRend = FindObjectOfType<VolumeRenderer>();
|
||||
VolumeRenderedObject volRend = FindObjectOfType<VolumeRenderedObject>();
|
||||
if (volRend == null)
|
||||
return;
|
||||
tf = volRend.tf;
|
||||
tf = volRend.transferFunction;
|
||||
|
||||
Color oldColour = GUI.color;
|
||||
float bgWidth = Mathf.Min(this.position.width - 20.0f, (this.position.height - 50.0f) * 2.0f);
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
[CustomEditor(typeof(VolumeRenderedObject))]
|
||||
public class VolumeRenderedObjectCustomInspector : Editor
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: af5b051c5cf4f824c999ee444c9acff6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,25 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
|
||||
public class VolumeRendererEditorFunctions
|
||||
{
|
||||
[MenuItem("Volume Rendering/Load dataset")]
|
||||
static void ShowWindow()
|
||||
{
|
||||
string file = EditorUtility.OpenFilePanel("Select a dataset to load", "DataFiles", "*.*");
|
||||
if(File.Exists(file))
|
||||
{
|
||||
DatasetImporterEditorWindow wnd = (DatasetImporterEditorWindow)EditorWindow.GetWindow(typeof(DatasetImporterEditorWindow));
|
||||
if (wnd != null)
|
||||
wnd.Close();
|
||||
|
||||
wnd = new DatasetImporterEditorWindow(file);
|
||||
wnd.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("File doesn't exist: " + file);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3b47c51242b1c10429411c0ce01c5760
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -8,7 +8,7 @@ Material:
|
|||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: DirectVolumeRenderingMaterial
|
||||
m_Shader: {fileID: 4800000, guid: f9df7f8cb5dda3a48a945ab37d6b0d83, type: 3}
|
||||
m_ShaderKeywords: MODE_DVR TF2D_ON _MODE_DVR _MODE_MIP
|
||||
m_ShaderKeywords: MODE_SURF _MODE_DVR _MODE_MIP
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
|
@ -77,7 +77,7 @@ Material:
|
|||
- _GlossyReflections: 1
|
||||
- _MaxVal: 1
|
||||
- _Metallic: 0
|
||||
- _MinVal: 0
|
||||
- _MinVal: 0.1
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
|
|
|
@ -6,7 +6,7 @@ Material:
|
|||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: TransferFunctionPaletteGUIMat
|
||||
m_Name: TransferFunction2DGUIMat
|
||||
m_Shader: {fileID: 4800000, guid: b0b396ea7426c8b4385f14d5e5a951ed, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
|
|
|
@ -21,7 +21,7 @@ GameObject:
|
|||
- component: {fileID: 4022122026797268}
|
||||
- component: {fileID: 33312357750855204}
|
||||
- component: {fileID: 23086139309309076}
|
||||
- component: {fileID: 114671375263017396}
|
||||
- component: {fileID: 114985090201080716}
|
||||
m_Layer: 0
|
||||
m_Name: VolumeRenderedObject
|
||||
m_TagString: Untagged
|
||||
|
@ -84,7 +84,7 @@ MeshFilter:
|
|||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 1758459268553486}
|
||||
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!114 &114671375263017396
|
||||
--- !u!114 &114985090201080716
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
|
@ -92,7 +92,7 @@ MonoBehaviour:
|
|||
m_GameObject: {fileID: 1758459268553486}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: a00a6dc9906286a46948a51d4f7c56ab, type: 3}
|
||||
m_Script: {fileID: 11500000, guid: acf4a5cf6519d714895a068f9a4e8456, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
tf2D: {fileID: 0}
|
||||
transferFunction2D: {fileID: 0}
|
||||
|
|
|
@ -251,45 +251,3 @@ Transform:
|
|||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 9.994, y: -21.144001, z: 0.49300003}
|
||||
--- !u!1001 &1540645132
|
||||
Prefab:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 4022122026797268, guid: 06d1ae9362ecddb44844bf342a6fc7f3, type: 2}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4022122026797268, guid: 06d1ae9362ecddb44844bf342a6fc7f3, type: 2}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4022122026797268, guid: 06d1ae9362ecddb44844bf342a6fc7f3, type: 2}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4022122026797268, guid: 06d1ae9362ecddb44844bf342a6fc7f3, type: 2}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4022122026797268, guid: 06d1ae9362ecddb44844bf342a6fc7f3, type: 2}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0.7071068
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4022122026797268, guid: 06d1ae9362ecddb44844bf342a6fc7f3, type: 2}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0.7071068
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4022122026797268, guid: 06d1ae9362ecddb44844bf342a6fc7f3, type: 2}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4022122026797268, guid: 06d1ae9362ecddb44844bf342a6fc7f3, type: 2}
|
||||
propertyPath: m_RootOrder
|
||||
value: 2
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_ParentPrefab: {fileID: 100100000, guid: 06d1ae9362ecddb44844bf342a6fc7f3, type: 2}
|
||||
m_IsPrefabParent: 0
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
public abstract class DatasetImporterBase
|
||||
{
|
||||
public abstract VolumeDataset Import();
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 693790aa0dad1104b8eca0e740092fd9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -12,7 +12,7 @@ public enum DataContentFormat
|
|||
Uint32
|
||||
}
|
||||
|
||||
public class RawDatasetImporter
|
||||
public class RawDatasetImporter : DatasetImporterBase
|
||||
{
|
||||
string filePath;
|
||||
private int dimX;
|
||||
|
@ -31,7 +31,7 @@ public class RawDatasetImporter
|
|||
this.skipBytes = skipBytes;
|
||||
}
|
||||
|
||||
public VolumeDataset Import()
|
||||
public override VolumeDataset Import()
|
||||
{
|
||||
VolumeDataset dataset = new VolumeDataset();
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 03893c9833273f240992663ef124c6a1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,6 @@
|
|||
public enum RenderMode
|
||||
{
|
||||
DirectVolumeRendering,
|
||||
MaximumIntensityProjectipon,
|
||||
IsosurfaceRendering
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bd1c234ee0e105046973293124d8566d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,5 +1,6 @@
|
|||
using UnityEngine;
|
||||
|
||||
[ExecuteInEditMode]
|
||||
public class SlicingPlane : MonoBehaviour
|
||||
{
|
||||
private MeshRenderer meshRenderer;
|
|
@ -0,0 +1,84 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
public class VolumeObjectFactory
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6b116dd3827f30444b1fee36feceb17d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,67 @@
|
|||
using UnityEngine;
|
||||
|
||||
public class VolumeRenderedObject : MonoBehaviour
|
||||
{
|
||||
[HideInInspector]
|
||||
public TransferFunction transferFunction;
|
||||
|
||||
[HideInInspector]
|
||||
public TransferFunction2D transferFunction2D;
|
||||
|
||||
[HideInInspector]
|
||||
public VolumeDataset dataset;
|
||||
|
||||
private RenderMode remderMode;
|
||||
|
||||
public SlicingPlane CreateSlicingPlane()
|
||||
{
|
||||
GameObject sliceRenderingPlane = GameObject.Instantiate(Resources.Load<GameObject>("SlicingPlane"));
|
||||
sliceRenderingPlane.transform.parent = transform;
|
||||
sliceRenderingPlane.transform.localPosition = Vector3.zero;
|
||||
sliceRenderingPlane.transform.localRotation = Quaternion.identity;
|
||||
MeshRenderer sliceMeshRend = sliceRenderingPlane.GetComponent<MeshRenderer>();
|
||||
sliceMeshRend.material = new Material(sliceMeshRend.sharedMaterial);
|
||||
Material sliceMat = sliceRenderingPlane.GetComponent<MeshRenderer>().sharedMaterial;
|
||||
sliceMat.SetTexture("_DataTex", dataset.texture);
|
||||
sliceMat.SetTexture("_TFTex", transferFunction.GetTexture());
|
||||
sliceMat.SetMatrix("_parentInverseMat", transform.worldToLocalMatrix);
|
||||
sliceMat.SetMatrix("_planeMat", Matrix4x4.TRS(sliceRenderingPlane.transform.position, sliceRenderingPlane.transform.rotation, Vector3.one)); // TODO: allow changing scale
|
||||
|
||||
return sliceRenderingPlane.GetComponent<SlicingPlane>();
|
||||
}
|
||||
|
||||
public void SetRenderMode(RenderMode mode)
|
||||
{
|
||||
remderMode = mode;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case RenderMode.DirectVolumeRendering:
|
||||
{
|
||||
GetComponent<MeshRenderer>().sharedMaterial.EnableKeyword("MODE_DVR");
|
||||
GetComponent<MeshRenderer>().sharedMaterial.DisableKeyword("MODE_MIP");
|
||||
GetComponent<MeshRenderer>().sharedMaterial.DisableKeyword("MODE_SURF");
|
||||
break;
|
||||
}
|
||||
case RenderMode.MaximumIntensityProjectipon:
|
||||
{
|
||||
GetComponent<MeshRenderer>().sharedMaterial.DisableKeyword("MODE_DVR");
|
||||
GetComponent<MeshRenderer>().sharedMaterial.EnableKeyword("MODE_MIP");
|
||||
GetComponent<MeshRenderer>().sharedMaterial.DisableKeyword("MODE_SURF");
|
||||
break;
|
||||
}
|
||||
case RenderMode.IsosurfaceRendering:
|
||||
{
|
||||
GetComponent<MeshRenderer>().sharedMaterial.DisableKeyword("MODE_DVR");
|
||||
GetComponent<MeshRenderer>().sharedMaterial.DisableKeyword("MODE_MIP");
|
||||
GetComponent<MeshRenderer>().sharedMaterial.EnableKeyword("MODE_SURF");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RenderMode GetRemderMode()
|
||||
{
|
||||
return remderMode;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: acf4a5cf6519d714895a068f9a4e8456
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,138 +0,0 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
public class VolumeRenderer : MonoBehaviour
|
||||
{
|
||||
public TransferFunction tf = null;
|
||||
public TransferFunction2D tf2D = null;
|
||||
public VolumeDataset volumeDataset = null;
|
||||
|
||||
private GameObject sliceRenderingPlane;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
string fileToLoad = "DataFiles//manix.dat";
|
||||
FileStream fs = new FileStream(fileToLoad, FileMode.Open);
|
||||
BinaryReader reader = new BinaryReader(fs);
|
||||
|
||||
ushort dimX = reader.ReadUInt16();
|
||||
ushort dimY = reader.ReadUInt16();
|
||||
ushort dimZ = reader.ReadUInt16();
|
||||
|
||||
reader.Close();
|
||||
fs.Close();
|
||||
|
||||
Debug.Log(dimX + ", " + dimY + ", " + dimZ);
|
||||
|
||||
int uDimension = dimX * dimY * dimZ;
|
||||
|
||||
RawDatasetImporter importer = new RawDatasetImporter(fileToLoad, dimX, dimY, dimZ, DataContentFormat.Int16, 6);
|
||||
VolumeDataset dataset = importer.Import();
|
||||
volumeDataset = dataset;
|
||||
|
||||
int maxRange = dataset.maxDataValue - dataset.minDataValue;
|
||||
//const float maxNormalisedMagnitude = 1.75f; // sqrt(1^2 + 1^2 + 1^2) = swrt(3) = a bit less than 1.75
|
||||
|
||||
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);
|
||||
|
||||
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();
|
||||
|
||||
tf.histogramTexture = HistogramTextureGenerator.GenerateHistogramTexture(dataset);
|
||||
|
||||
tf2D = new TransferFunction2D();
|
||||
tf2D.AddBox(0.05f, 0.1f, 0.8f, 0.7f, Color.white, 0.4f);
|
||||
|
||||
GetComponent<MeshRenderer>().sharedMaterial.SetTexture("_DataTex", tex);
|
||||
GetComponent<MeshRenderer>().sharedMaterial.SetTexture("_NoiseTex", noiseTexture);
|
||||
GetComponent<MeshRenderer>().sharedMaterial.SetTexture("_TFTex", tfTexture);
|
||||
|
||||
GetComponent<MeshRenderer>().sharedMaterial.EnableKeyword("MODE_DVR");
|
||||
GetComponent<MeshRenderer>().sharedMaterial.DisableKeyword("MODE_MIP");
|
||||
GetComponent<MeshRenderer>().sharedMaterial.DisableKeyword("MODE_SURF");
|
||||
}
|
||||
|
||||
public SlicingPlane CreateSlicingPlane()
|
||||
{
|
||||
sliceRenderingPlane = GameObject.Instantiate(Resources.Load<GameObject>("SlicingPlane"));
|
||||
sliceRenderingPlane.transform.parent = transform;
|
||||
sliceRenderingPlane.transform.localPosition = Vector3.zero;
|
||||
sliceRenderingPlane.transform.localRotation = Quaternion.identity;
|
||||
MeshRenderer sliceMeshRend = sliceRenderingPlane.GetComponent<MeshRenderer>();
|
||||
sliceMeshRend.material = new Material(sliceMeshRend.sharedMaterial);
|
||||
Material sliceMat = sliceRenderingPlane.GetComponent<MeshRenderer>().sharedMaterial;
|
||||
sliceMat.SetTexture("_DataTex", volumeDataset.texture);
|
||||
sliceMat.SetTexture("_TFTex", tf.GetTexture());
|
||||
sliceMat.SetMatrix("_parentInverseMat", transform.worldToLocalMatrix);
|
||||
sliceMat.SetMatrix("_planeMat", Matrix4x4.TRS(sliceRenderingPlane.transform.position, sliceRenderingPlane.transform.rotation, Vector3.one)); // TODO: allow changing scale
|
||||
|
||||
return sliceRenderingPlane.GetComponent<SlicingPlane>();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.A))
|
||||
{
|
||||
GetComponent<MeshRenderer>().sharedMaterial.EnableKeyword("MODE_DVR");
|
||||
GetComponent<MeshRenderer>().sharedMaterial.DisableKeyword("MODE_MIP");
|
||||
GetComponent<MeshRenderer>().sharedMaterial.DisableKeyword("MODE_SURF");
|
||||
}
|
||||
else if (Input.GetKeyDown(KeyCode.S))
|
||||
{
|
||||
GetComponent<MeshRenderer>().sharedMaterial.DisableKeyword("MODE_DVR");
|
||||
GetComponent<MeshRenderer>().sharedMaterial.EnableKeyword("MODE_MIP");
|
||||
GetComponent<MeshRenderer>().sharedMaterial.DisableKeyword("MODE_SURF");
|
||||
}
|
||||
else if (Input.GetKeyDown(KeyCode.D))
|
||||
{
|
||||
GetComponent<MeshRenderer>().sharedMaterial.DisableKeyword("MODE_DVR");
|
||||
GetComponent<MeshRenderer>().sharedMaterial.DisableKeyword("MODE_MIP");
|
||||
GetComponent<MeshRenderer>().sharedMaterial.EnableKeyword("MODE_SURF");
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче