PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/Main/src/Microsoft.Research.Visualization3D/Providers/Isosurfaces/Metaball.cs

#
C# | 229 lines | 178 code | 41 blank | 10 comment | 23 complexity | 1d27ed9308ce03f4fd434d04b8bcc677 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using Microsoft.Research.Visualization3D.VertexStructures;
  4. using SlimDX.Direct3D9;
  5. using Microsoft.Research.Visualization3D.CameraUtilities;
  6. using SlimDX;
  7. using Microsoft.Research.Visualization3D.Auxilaries;
  8. using System.Windows.Threading;
  9. using System.Diagnostics;
  10. using Microsoft.Research.Visualization3D.MainLoops;
  11. using System.Threading;
  12. namespace Microsoft.Research.Visualization3D.Isosurfaces
  13. {
  14. public partial class Metaball : DrawableComponent
  15. {
  16. List<MetaballVertex> vertexList;
  17. int primitiveCount;
  18. int iDataSetSizeX;
  19. int iDataSetSizeY;
  20. int iDataSetSizeZ;
  21. VertexBuffer vb;
  22. public Metaball(DX3DHost host, Visualization3DDataSource dataSource) :
  23. base(host, dataSource)
  24. {
  25. iDataSetSizeX = dataSource.DisplayData.GetLength(0);
  26. iDataSetSizeY = dataSource.DisplayData.GetLength(1);
  27. iDataSetSizeZ = dataSource.DisplayData.GetLength(2);
  28. this.WpfDispatcher = Dispatcher.CurrentDispatcher;
  29. }
  30. public override void Initialize()
  31. {
  32. if (effect == null)
  33. {
  34. effect = Effect.FromStream(device, this.GetType().Assembly.GetManifestResourceStream("Microsoft.Research.Visualization3D.Shaders.PerPixelLightning.fx"), ShaderFlags.None);
  35. }
  36. SetCamera();
  37. vertexList = new List<MetaballVertex>();
  38. Color3 mbColor = RgbPalette.GetColor(fTargetValue, dataSource.Maximum, dataSource.Minimum, dataSource.MissingValue);
  39. effect.SetValue("mbColor", new Vector4(mbColor.Red, mbColor.Green, mbColor.Blue, 1.0f));
  40. MarchingCubes();
  41. Completed();
  42. base.Initialize();
  43. }
  44. //Calling Cube building function for each voxel
  45. public void MarchingCubes()
  46. {
  47. vertexList = new List<MetaballVertex>();
  48. for (int iX = 0; iX < iDataSetSizeX - 1; iX++)
  49. for (int iY = 0; iY < iDataSetSizeY - 1; iY++)
  50. for (int iZ = 0; iZ < iDataSetSizeZ - 1; iZ++)
  51. {
  52. vMarchCube(iX, iY, iZ, 1.0f);
  53. }
  54. }
  55. float fGetOffset(float fValue1, float fValue2, float fValueDesired)
  56. {
  57. double fDelta = fValue2 - fValue1;
  58. if (fDelta == 0.0)
  59. {
  60. return 0.5f;
  61. }
  62. return (fValueDesired - fValue1) / (float)fDelta;
  63. }
  64. float fSample(float fX, float fY, float fZ)
  65. {
  66. return MathHelper.GetValue(new Vector3(fX, fY, fZ), dataSource.DisplayData);
  67. }
  68. //vGetColor fins color via point and normal
  69. void vGetColor(ref Vector3 rfColor, Vector3 rfPosition, Vector3 rfNormal)
  70. {
  71. float fX = rfNormal.X;
  72. float fY = rfNormal.Y;
  73. float fZ = rfNormal.Z;
  74. rfColor.X = (float)((fX > 0.0 ? fX : 0.0) + (fY < 0.0 ? -0.5 * fY : 0.0) + (fZ < 0.0 ? -0.5 * fZ : 0.0));
  75. rfColor.Y = (float)((fY > 0.0 ? fY : 0.0) + (fZ < 0.0 ? -0.5 * fZ : 0.0) + (fX < 0.0 ? -0.5 * fX : 0.0));
  76. rfColor.Z = (float)((fZ > 0.0 ? fZ : 0.0) + (fX < 0.0 ? -0.5 * fX : 0.0) + (fY < 0.0 ? -0.5 * fY : 0.0));
  77. }
  78. //vGetNormal() Calculates normal via gradient to point
  79. void vGetNormal(ref Vector3 rfNormal, float fX, float fY, float fZ)
  80. {
  81. rfNormal.X = MathHelper.GetValue(new Vector3(fX - 0.01f, fY, fZ), dataSource.DisplayData) - MathHelper.GetValue(new Vector3(fX + 0.01f, fY, fZ), dataSource.DisplayData);
  82. rfNormal.Y = MathHelper.GetValue(new Vector3(fX, fY - 0.01f, fZ), dataSource.DisplayData) - MathHelper.GetValue(new Vector3(fX, fY + 0.01f, fZ), dataSource.DisplayData);
  83. rfNormal.Z = MathHelper.GetValue(new Vector3(fX, fY, fZ - 0.01f), dataSource.DisplayData) - MathHelper.GetValue(new Vector3(fX, fY, fZ + 0.01f), dataSource.DisplayData);
  84. if (rfNormal.Length() > 0)
  85. rfNormal.Normalize();
  86. }
  87. //Find part of Surface for current voxel
  88. void vMarchCube(float fX, float fY, float fZ, float fScale)
  89. {
  90. int iCorner, iVertex, iVertexTest, iEdge, iTriangle, iFlagIndex, iEdgeFlags;
  91. float fOffset;
  92. Vector3 sColor = Vector3.Zero;
  93. float[] afCubeValue = new float[8];
  94. Vector3[] asEdgeVertex = new Vector3[12];
  95. Vector3[] asEdgeNorm = new Vector3[12];
  96. //Find value in voxel's knots
  97. for (iVertex = 0; iVertex < 8; iVertex++)
  98. {
  99. afCubeValue[iVertex] = (float)dataSource.DisplayData[(int)(fX + a2fVertexOffset[iVertex, 0]), (int)(fY + a2fVertexOffset[iVertex, 1]), (int)(fZ + a2fVertexOffset[iVertex, 2])];
  100. if (afCubeValue[iVertex] == dataSource.MissingValue) return;
  101. }
  102. //Checking intersections via table
  103. iFlagIndex = 0;
  104. for (iVertexTest = 0; iVertexTest < 8; iVertexTest++)
  105. {
  106. if (afCubeValue[iVertexTest] <= fTargetValue)
  107. iFlagIndex |= 1 << iVertexTest;
  108. }
  109. //Finally, get our surface configuration
  110. iEdgeFlags = aiCubeEdgeFlags[iFlagIndex];
  111. //if our surface doesn't intersect voxel
  112. if (iEdgeFlags == 0)
  113. {
  114. return;
  115. }
  116. //Building vertices
  117. for (iEdge = 0; iEdge < 12; iEdge++)
  118. {
  119. if ((iEdgeFlags & (1 << iEdge)) != 0)
  120. {
  121. fOffset = fGetOffset(afCubeValue[a2iEdgeConnection[iEdge, 0]],
  122. afCubeValue[a2iEdgeConnection[iEdge, 1]], fTargetValue);
  123. asEdgeVertex[iEdge].X = (float)(fX + (a2fVertexOffset[a2iEdgeConnection[iEdge, 0], 0] + fOffset * a2fEdgeDirection[iEdge, 0]) * fScale);
  124. asEdgeVertex[iEdge].Y = (float)(fY + (a2fVertexOffset[a2iEdgeConnection[iEdge, 0], 1] + fOffset * a2fEdgeDirection[iEdge, 1]) * fScale);
  125. asEdgeVertex[iEdge].Z = (float)(fZ + (a2fVertexOffset[a2iEdgeConnection[iEdge, 0], 2] + fOffset * a2fEdgeDirection[iEdge, 2]) * fScale);
  126. vGetNormal(ref asEdgeNorm[iEdge], asEdgeVertex[iEdge].X, asEdgeVertex[iEdge].Y, asEdgeVertex[iEdge].Z);
  127. }
  128. }
  129. //Building triangles
  130. for (iTriangle = 0; iTriangle < 5; iTriangle++)
  131. {
  132. if (a2iTriangleConnectionTable[iFlagIndex, 3 * iTriangle] < 0)
  133. break;
  134. for (iCorner = 0; iCorner < 3; iCorner++)
  135. {
  136. iVertex = a2iTriangleConnectionTable[iFlagIndex, 3 * iTriangle + iCorner];
  137. vertexList.Add(new MetaballVertex(
  138. asEdgeVertex[iVertex],
  139. asEdgeNorm[iVertex]
  140. ));
  141. }
  142. }
  143. }
  144. protected override void SetCamera()
  145. {
  146. camera.CameraScale = 12.0f;
  147. float cameraScale = 2.0f;
  148. camera.Location = cameraScale * new Vector3(dataSource.DisplayData.GetLength(0), dataSource.DisplayData.GetLength(1), dataSource.DisplayData.GetLength(2));
  149. camera.Target = new Vector3(dataSource.DisplayData.GetLength(0) / 2f, dataSource.DisplayData.GetLength(1) / 2f, dataSource.DisplayData.GetLength(2) / 2f);
  150. camera.Up = new Vector3(0, 1, 0);
  151. effect.SetValue("world", Matrix.Identity);
  152. effect.SetValue("view", camera.ViewMatrix);
  153. effect.SetValue("projection", camera.ProjectionMatrix);
  154. effect.SetValue("cameraPosition", camera.Location);
  155. effect.SetValue("lightPosition", camera.Location);
  156. effect.SetValue("ambientLightColor", new Vector4(1.0f, 1.0f, 1.0f, 1));
  157. effect.SetValue("diffuseLightColor", new Vector4(1.0f, 1.0f, 1.0f, 1));
  158. effect.SetValue("specularLightColor", new Vector4(1.0f, 1.0f, 1.0f, 1));
  159. effect.SetValue("specularPower", 1.0f);
  160. effect.SetValue("specularIntensity", 1.0f);
  161. }
  162. public override void Draw(TimeEntity timeEntity)
  163. {
  164. if (primitiveCount > 0)
  165. {
  166. effect.Technique = new EffectHandle("PerPixelDiffuseAndPhongMetaball");
  167. device.SetStreamSource(0, vb, 0, MetaballVertex.SizeInBytes);
  168. device.VertexFormat = MetaballVertex.Format;
  169. int passes = effect.Begin();
  170. for (int i = 0; i < passes; i++)
  171. {
  172. effect.BeginPass(i);
  173. device.DrawPrimitives(PrimitiveType.TriangleList, 0, primitiveCount);
  174. effect.EndPass();
  175. }
  176. effect.End();
  177. }
  178. }
  179. public override void Update(TimeEntity timeEntity)
  180. {
  181. effect.SetValue("world", Matrix.Identity);
  182. effect.SetValue("view", camera.ViewMatrix);
  183. effect.SetValue("projection", camera.ProjectionMatrix);
  184. effect.SetValue("cameraPosition", camera.Location);
  185. effect.SetValue("lightPosition", camera.Location);
  186. }
  187. }
  188. }