1 #region Using Statements
3 using System.Collections.Generic;
7 using Microsoft.Xna.Framework;
8 using Microsoft.Xna.Framework.Audio;
9 using Microsoft.Xna.Framework.Content;
10 using Microsoft.Xna.Framework.GamerServices;
11 using Microsoft.Xna.Framework.Graphics;
12 using Microsoft.Xna.Framework.Input;
13 using Microsoft.Xna.Framework.Media;
14 using Microsoft.Xna.Framework.Net;
15 using Microsoft.Xna.Framework.Storage;
17 using Microsoft.Xna.Framework.Graphics.PackedVector;
30 #region Ray Casting parameters
31 public Vector3 stepSize;
32 public Vector4 scaleFactor;
33 public int iterations;
34 public float scaleSteps = 1.0f;
36 public float slice = 0.5f;
39 #region transfer function
40 private List<TransferControlPoint> colorControlPoints;
41 private List<TransferControlPoint> alphaControlPoints;
42 public Texture2D transferTexture;
43 public Texture2D transferTextureAlpha;
47 private List<float> densityValues;
48 private float[] densityArray;
49 private float[] distinctDensityValuesArray;
50 private int[] countDensityValuesArray;
52 private Vector3[] gradients;
54 public Matrix worldMatrix;
59 ushort sizeX, sizeY, sizeZ;
61 private String fileName;
63 public Texture3D volumeData;
64 public Texture3D volumeGradients;
69 int texturesSaved = 0;
71 ContentManager content;
75 private int currentView = 0;
83 set { camera = value; }
84 get {
return camera; }
86 public int CurrentCamera
88 set { currentView = value; }
91 public Texture3D VolumeData
93 get {
return volumeData; }
95 public Vector3 DataDimensions
97 get {
return new Vector3(sizeX, sizeY, sizeZ); }
102 public Data(
string _fileName)
109 worldMatrix = Matrix.Identity;
111 string a =
"" + Directory.GetParent((
string)Directory.GetCurrentDirectory());
112 string b =
"" + Directory.GetParent(a);
113 string c =
"" + Directory.GetParent(b);
115 this.fileName = c +
"\\" + _fileName;
117 if (
string.IsNullOrEmpty(fileName))
119 throw new ArgumentNullException(fileName);
122 if (!File.Exists(fileName))
124 Console.WriteLine(fileName);
125 throw new ArgumentException(
"file not found: " + fileName);
147 #region LoadContent()
157 Console.WriteLine(
"LOADING DATA CONTENT");
161 #region calculate Ray Casting Parameters
163 scaleSteps = GameProperties.Instance.currSampleDist;
164 float max = (float)Math.Max(sizeX, Math.Max(sizeY, sizeZ));
165 stepSize = Vector3.One / max;
172 worldMatrix = Matrix.CreateTranslation(
new Vector3(-(sizeX / max) / 2.0f,
173 -(sizeY / max) / 2.0f,
174 -(sizeZ / max) / 2.0f));
177 iterations = (int)(max * (1.0f / scaleSteps));
180 Vector3 sizeVector =
new Vector3(sizeX, sizeY, sizeZ);
181 Vector3 scale = Vector3.One / ((Vector3.One * max) / sizeVector);
182 scaleFactor =
new Vector4(scale.X, scale.Y, scale.Z, 1.0f);
185 #region content manager
187 if (GameProperties.Instance.debugOutput)
189 Console.WriteLine(
"creating content manager");
191 content = Services.
GetService(typeof(ContentManager)) as ContentManager;
195 content =
new ContentManager(Services,
"Content");
196 Services.AddService<ContentManager>(content);
197 if (GameProperties.Instance.debugOutput)
199 Console.WriteLine(
"content manager created");
204 cube = content.Load<Model>(
"Models/box");
205 if (GameProperties.Instance.debugOutput)
207 Console.WriteLine(
"cube loaded");
212 Console.WriteLine(
"Problem loading cube: " + e);
217 colorControlPoints = GameProperties.Instance.colorControlPoints;
218 alphaControlPoints = GameProperties.Instance.alphaControlPoints;
220 transferTexture =
new Texture2D(GraphicsDevice, 256, 1,
false, SurfaceFormat.Color); ;
223 setSliceRange(sizeX, sizeY, sizeZ);
228 #region loadDatafromFile()
229 private void loadDatafromFile()
240 if (GameProperties.Instance.debugOutput)
242 Console.WriteLine(
"LOADING DATA FROM FILE");
245 Stream file =
new FileStream(fileName, FileMode.Open);
247 BinaryReader reader =
new BinaryReader(file);
250 sizeX = reader.ReadUInt16();
251 sizeY = reader.ReadUInt16();
252 sizeZ = reader.ReadUInt16();
256 volumeData =
new Texture3D(GraphicsDevice, sizeX, sizeY, sizeZ,
false, SurfaceFormat.Rgba64);
258 ushort[] buffer =
new ushort[sizeX * sizeY * sizeZ];
261 while (reader.BaseStream.Position < reader.BaseStream.Length)
264 buffer[l] = reader.ReadUInt16();
269 if (GameProperties.Instance.debugOutput)
271 Console.WriteLine(
"LOADING DATA FROM FILE");
276 densityValues =
new List<float>();
277 float maxValue = 1.0f / buffer.Max();
278 for (
int i = 0; i < buffer.Length; i++)
280 densityValues.Add((
float)buffer[i] * maxValue);
286 GameProperties.Instance.dataOrigin =
new Vector3(0.5f, 0.5f, sizeZ / 2.0f);
288 #region add gradients to VolumeData
290 if (GameProperties.Instance.enableGaussFilter) { filterGaussian(0.3f); }
291 if (GameProperties.Instance.enableAvgFilter) { filterNxNxN(3,
true); }
297 calculateGradients();
299 filterNxNxN(3,
false);
303 #region add black border
305 for (
int k = 0; k < sizeZ; k++)
307 for (
int j = 0; j < sizeY; j++)
309 for (
int i = 0; i < sizeX; i++)
311 int idx = i + (j * sizeX) + (k * sizeX * sizeY);
312 if (!((i >= 1 && i < sizeX - 1) &&
313 (j >= 1 && i < sizeY - 1) &&
314 (k >= 1 && k < sizeZ - 1)))
317 densityValues[idx] = 0.0f;
326 Rgba64[] densityVectors =
new Rgba64[buffer.Length];
327 for (
int i = 0; i < buffer.Length; i++)
329 densityVectors[i] =
new Rgba64(gradients[i].X,
337 volumeData.SetData<Rgba64>(densityVectors);
340 densityValues.Sort();
348 if (GameProperties.Instance.debugOutput)
350 Console.WriteLine(
"DATA LOADED FROM FILE");
355 #region sortDensityValues()
363 private void sortDensityValues()
366 List<float> distinctDensityValues =
new List<float>();
367 List<int> countDensityValues =
new List<int>();
375 for (
int i = 0; i < densityValues.Count(); i++)
377 int value1 = (int)(densityValues[i] * 255);
380 while (i < (densityValues.Count() - 1))
382 int value2 = (int)(densityValues[i + 1] * 255);
383 if ((value1 == value2))
401 distinctDensityValues.Add(value1);
402 countDensityValues.Add(count);
405 distinctDensityValuesArray = distinctDensityValues.ToArray();
406 countDensityValuesArray = countDensityValues.ToArray();
408 GameProperties.Instance.distinctDensityValues = distinctDensityValuesArray;
409 GameProperties.Instance.countDensityValues = countDensityValuesArray;
417 protected override void Update()
431 #region move camera TODO
445 #region set parameters for rendering
458 protected override void Draw()
478 #region DrawCoordinateSystem()
485 Console.WriteLine(
"DRAWING COORDINATE SYSTEM");
486 #region coordinate system
488 BasicEffect basicEffect =
new BasicEffect(GraphicsDevice);
489 GraphicsDevice.DepthStencilState = DepthStencilState.None;
491 basicEffect.LightingEnabled =
false;
492 basicEffect.TextureEnabled =
false;
493 basicEffect.VertexColorEnabled =
true;
494 basicEffect.World = Matrix.Identity;
496 basicEffect.View = camera.
View;
498 foreach (EffectPass pass
in basicEffect.CurrentTechnique.Passes)
501 VertexPositionColor[] pointList = {
503 new VertexPositionColor(
new Vector3(0.0f, 0.0f, 0.0f), Color.DarkBlue),
504 new VertexPositionColor(
new Vector3(0.0f, 0.0f, -3000.0f), Color.DarkBlue),
505 new VertexPositionColor(
new Vector3(0.0f, 0.0f, 0.0f), Color.Blue),
506 new VertexPositionColor(
new Vector3(0.0f, 0.0f, 3000.0f), Color.Blue),
508 new VertexPositionColor(
new Vector3(0.0f, 0.0f, 0.0f), Color.DarkGreen),
509 new VertexPositionColor(
new Vector3(0.0f, -3000.0f, 0.0f), Color.DarkGreen),
510 new VertexPositionColor(
new Vector3(0.0f, 0.0f, 0.0f), Color.Green),
511 new VertexPositionColor(
new Vector3(0.0f, 3000.0f, 0.0f), Color.Green),
513 new VertexPositionColor(
new Vector3(0.0f, 0.0f, 0.0f), Color.DarkRed),
514 new VertexPositionColor(
new Vector3(-3000.0f, 0.0f, 0.0f), Color.DarkRed),
515 new VertexPositionColor(
new Vector3(0.0f, 0.0f, 0.0f), Color.Red),
516 new VertexPositionColor(
new Vector3(3000.0f, 0.0f, 0.0f), Color.Red),
518 new VertexPositionColor(
new Vector3(10.0f + 2.5f, 5.0f, 0.0f), Color.DarkRed),
519 new VertexPositionColor(
new Vector3(10.0f + 1.25f, 1.25f, 0.0f), Color.DarkRed),
520 new VertexPositionColor(
new Vector3(10.0f + 1.25f, 5.0f, 0.0f), Color.DarkRed),
521 new VertexPositionColor(
new Vector3(10.0f + 2.5f, 1.25f, 0.0f), Color.DarkRed),
523 new VertexPositionColor(
new Vector3(1.875f, 10.0f + 3.125f, 0.0f), Color.DarkGreen),
524 new VertexPositionColor(
new Vector3(1.875f, 10.0f + 1.125f, 0.0f), Color.DarkGreen),
525 new VertexPositionColor(
new Vector3(1.875f, 10.0f + 3.125f, 0.0f), Color.DarkGreen),
526 new VertexPositionColor(
new Vector3(2.5f, 10.0f + 5.0f, 0.0f), Color.DarkGreen),
527 new VertexPositionColor(
new Vector3(1.875f, 10.0f + 3.125f, 0.0f), Color.DarkGreen),
528 new VertexPositionColor(
new Vector3(1.125f, 10 + 5.0f, 0.0f), Color.DarkGreen),
530 new VertexPositionColor(
new Vector3(0.0f, 5.0f, 10.0f + 2.5f), Color.DarkBlue),
531 new VertexPositionColor(
new Vector3(0.0f, 5.0f, 10.0f + 1.25f), Color.DarkBlue),
532 new VertexPositionColor(
new Vector3(0.0f, 1.25f, 10.0f + 2.5f), Color.DarkBlue),
533 new VertexPositionColor(
new Vector3(0.0f, 1.25f, 10.0f + 1.25f), Color.DarkBlue),
534 new VertexPositionColor(
new Vector3(0.0f, 1.25f, 10.0f + 2.5f), Color.DarkBlue),
535 new VertexPositionColor(
new Vector3(0.0f, 5.0f, 10.0f + 1.25f), Color.DarkBlue)
538 short[] lineListIndices =
new short[28] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 };
539 GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>(
540 PrimitiveType.LineList,
549 GraphicsDevice.DepthStencilState = DepthStencilState.Default;
556 #region transfer function
563 colorControlPoints = GameProperties.Instance.colorControlPoints;
564 alphaControlPoints = GameProperties.Instance.alphaControlPoints;
567 Color[] colorArray =
new Color[256];
568 float[] alphaArray =
new float[256];
570 #region interpolate between ControlPoints
573 colorControlPoints.Sort(delegate(TransferControlPoint p1,
574 TransferControlPoint p2) {
return p1.isoValue.CompareTo(p2.isoValue); });
575 alphaControlPoints.Sort(delegate(TransferControlPoint p1,
576 TransferControlPoint p2) {
return p1.isoValue.CompareTo(p2.isoValue); });
579 for (
int i = 0; i < colorControlPoints[0].isoValue; i++)
581 colorArray[i] =
new Color(0.0f, 0.0f, 0.0f, 0.0f);
582 alphaArray[i] = 0.0f;
585 for (
int j = 0; j < colorControlPoints.Count - 1; j++)
587 for (
int i = colorControlPoints[j].isoValue; i <= colorControlPoints[j + 1].isoValue; i++)
589 amount = (((float)i - colorControlPoints[j].isoValue) /
590 (colorControlPoints[j + 1].isoValue - colorControlPoints[j].isoValue));
591 colorArray[i] = Color.Lerp(
new Color(colorControlPoints[j].color),
592 new Color(colorControlPoints[j + 1].color), amount);
595 alphaArray[i] = alphaControlPoints[j].color.W * (1.0f - amount) +
596 alphaControlPoints[j + 1].color.W * amount;
598 colorArray[i].A = (byte)(alphaArray[i] * 255);
603 for (
int i = colorControlPoints[colorControlPoints.Count - 1].isoValue + 1; i < 256; i++)
605 colorArray[i] =
new Color(0.0f, 0.0f, 0.0f, 0.0f);
606 alphaArray[i] = 0.0f;
621 #region write to textures
623 transferTexture =
new Texture2D(GraphicsDevice, 256, 1,
false, SurfaceFormat.Color);
624 transferTextureAlpha =
new Texture2D(GraphicsDevice, 256, 1,
false, SurfaceFormat.Color);
627 Color[] alphaValues =
new Color[256];
629 for (
int i = 0; i < 256; i++)
638 alphaValues[i] =
new Color(alphaArray[i], alphaArray[i], alphaArray[i], alphaArray[i]);
643 transferTexture.SetData<Color>(colorArray);
644 transferTextureAlpha.SetData<Color>(alphaValues);
661 private float getSampleAt(
int x,
int y,
int z)
663 x = (int)MathHelper.Clamp(x, 0, sizeX - 1);
664 y = (int)MathHelper.Clamp(y, 0, sizeY - 1);
665 z = (int)MathHelper.Clamp(z, 0, sizeZ - 1);
669 int arrayIndex = x + y * sizeX + z * sizeX * sizeY;
673 return densityValues[arrayIndex];
685 private void calculateGradients()
693 int sampleSize = GameProperties.Instance.gradientSampleSize;
695 gradients =
new Vector3[sizeX * sizeY * sizeZ];
697 Vector3 normal = Vector3.Zero;
701 for (
int z = 0; z < sizeZ; z++)
703 for (
int y = 0; y < sizeY; y++)
705 for (
int x = 0; x < sizeX; x++)
708 Vector3 gradient =
new Vector3(
709 getSampleAt(x + sampleSize, y, z) - getSampleAt(x - sampleSize, y, z),
710 getSampleAt(x, y + sampleSize, z) - getSampleAt(x, y - sampleSize, z),
711 getSampleAt(x, y, z + sampleSize) - getSampleAt(x, y, z - sampleSize));
714 gradients[i] = Vector3.Normalize(gradient);
720 if (
float.IsNaN(gradients[i].X)) gradients[i] = Vector3.Zero;
731 private void scaleGradients()
733 for (
int i = 0; i < gradients.Length; i++)
736 gradients[i].X = (gradients[i].X + 1.0f) / 2.0f; gradients[i].Y = (gradients[i].Y + 1.0f) / 2.0f; gradients[i].Z = (gradients[i].Z + 1.0f) / 2.0f;
746 private void filterNxNxN(
int n = 3,
bool filterData =
false)
748 List<float> valuesTmpSingle =
new List<float>();
749 List<Vector3> valuesTmp =
new List<Vector3>();
751 for (
int z = 0; z < sizeZ; z++)
753 for (
int y = 0; y < sizeY; y++)
755 for (
int x = 0; x < sizeX; x++)
759 valuesTmpSingle.Add(sampleNxNxNSingle(x, y, z, n));
763 valuesTmp.Add(sampleNxNxN(x, y, z, n));
769 if (filterData) { densityValues = valuesTmpSingle; }
770 else {gradients = valuesTmp.ToArray<Vector3>(); }
782 private Vector3 sampleNxNxN(
int x,
int y,
int z,
int n)
786 Vector3 average = Vector3.Zero;
789 for (
int k = z - n; k <= z + n; k++)
791 for (
int j = y - n; j <= y + n; j++)
793 for (
int i = x - n; i <= x + n; i++)
795 if (isInBounds(i, j, k))
797 average += gradients[i + (j * sizeX) + (k * sizeX * sizeY)];
804 average /= (float)num;
805 if (average.X != 0.0f && average.Y != 0.0f && average.Z != 0.0f)
818 private bool isInBounds(
int x,
int y,
int z)
820 return ((x >= 0 && x < sizeX) &&
821 (y >= 0 && y < sizeY) &&
822 (z >= 0 && z < sizeZ));
834 private float sampleNxNxNSingle(
int x,
int y,
int z,
int n)
838 float average = 0.0f;
841 for (
int k = z - n; k <= z + n; k++)
843 for (
int j = y - n; j <= y + n; j++)
845 for (
int i = x - n; i <= x + n; i++)
847 if (isInBounds(i, j, k))
849 average += densityValues[i + (j * sizeX) + (k * sizeX * sizeY)];
856 average /= (float)num;
865 private void filterGaussian(
float sigma)
867 List<float> valuesTmpSingle =
new List<float>();
868 float[] gaussianKernel = calculateGaussianKernel(sigma);
870 for (
int z = 0; z < sizeZ; z++)
872 for (
int y = 0; y < sizeY; y++)
874 for (
int x = 0; x < sizeX; x++)
877 valuesTmpSingle.Add(sampleGaussKernel(x, y, z, gaussianKernel));
883 densityValues = valuesTmpSingle;
894 private float sampleGaussKernel(
int x,
int y,
int z,
float[] gaussianKernel)
896 int n = (int)Math.Pow(gaussianKernel.Length, 1 / 3);
899 float average = 0.0f;
900 int kk = 0;
int jk = 0;
int ik = 0;
902 for (
int k = z - n; k <= z + n; k++)
904 for (
int j = y - n; j <= y + n; j++)
906 for (
int i = x - n; i <= x + n; i++)
908 if (isInBounds(i, j, k))
910 average += densityValues[i + (j * sizeX) + (k * sizeX * sizeY)] * gaussianKernel[ik + (jk * n) + (kk * n * n)];
929 private float[] calculateGaussianKernel(
float sigma)
932 int kernelSize = (int)(6 * (sigma) - 1);
933 if (kernelSize < 3) kernelSize = 3;
935 int width = kernelSize;
int height = kernelSize;
int depth = kernelSize;
937 float[] gaussianKernel =
new float[width * height * depth];
939 int x_offset = (-1) * (width - 1) / 2;
940 int y_offset = (-1) * (height - 1) / 2;
941 int z_offset = (-1) * (depth - 1) / 2;
945 for (
int k = 0; k < depth; k++)
947 y_offset = (-1) * (width - 1) / 2;
948 for (
int j = 0; j < width; j++)
950 x_offset = (-1) * (width - 1) / 2;
951 for (
int i = 0; i < width; i++)
953 int idx = k * (width * width) + j * (width) + i;
956 gaussianKernel[idx] = 1 / (float)(Math.Sqrt(2 * Math.PI) * sigma * Math.Sqrt(2 * Math.PI) * sigma * Math.Sqrt(2 * Math.PI) * sigma * Math.Exp(-((x_offset * x_offset + y_offset * y_offset + z_offset * z_offset) / (2 * sigma * sigma))));
958 norm = norm + gaussianKernel[idx];
960 x_offset = x_offset + 1;
962 y_offset = y_offset + 1;
964 z_offset = z_offset + 1;
968 for (
int i = 0; i < gaussianKernel.Length; i++)
970 gaussianKernel[i] = gaussianKernel[i] / norm;
973 return gaussianKernel;
978 #region help functions
979 private void saveScreenshot(Texture2D texture, String name)
983 FileStream stream = File.OpenWrite(name +
".png");
984 texture.SaveAsPng(stream, texture.Width, texture.Height);
989 Console.WriteLine(
"Save Screenshot: ");
990 Console.WriteLine(e);
999 private void saveScreenshot(Texture2D texture, String name, String ext)
1001 Console.WriteLine(
"saving " + name);
1004 if (!name.ElementAt(name.Length - 4).Equals(
".")) name = name +
"." + ext;
1005 FileStream stream = File.OpenWrite(name);
1009 texture.SaveAsPng(stream, texture.Width, texture.Height);
1012 texture.SaveAsJpeg(stream, texture.Width, texture.Height);
1015 if (name.ElementAt(name.Length - 4).Equals(
".")) name = name.Substring(0, name.Length - 4);
1016 name = name +
".png";
1017 texture.SaveAsPng(stream, texture.Width, texture.Height);
1024 Console.WriteLine(
"Save Screenshot: ");
1025 Console.WriteLine(e);
1031 private void setSliceRange(
int xRange,
int yRange,
int zRange)
1033 GameProperties.Instance.xDataRange = xRange;
1034 GameProperties.Instance.yDataRange = yRange;
1035 GameProperties.Instance.zDataRange = zRange;