public SurfacePoint(Vector3 position, Triangle face, Vector3 barycentricCoords, float surfaceOffset, Matrix3 orientationMatrix) { Position = position; Face = face; BarycentricCoords = barycentricCoords; SurfaceOffset = surfaceOffset; Psi = 0; OriginalMatrix = orientationMatrix; }
public SurfacePoint(Vector3 position, Triangle face, Vector3 barycentricCoords, float surfaceOffset, float psi) { Position = position; Face = face; BarycentricCoords = barycentricCoords; SurfaceOffset = surfaceOffset; Psi = psi; OriginalMatrix = face.GetPlaneMatrix3(); }
public SurfacePatch(Membrane membrane, string name, Color color, IEnumerable<Triangle> triangles) { Membrane = membrane; Name = name; Color = color; Dictionary<Vertex, Vertex> VertexToTransformed = new Dictionary<Vertex, Vertex>(); List<Triangle> NewTriangles = new List<Triangle>(triangles.Count()); foreach (var t in triangles) { foreach (var v in t.Vertices) if (!VertexToTransformed.ContainsKey(v)) VertexToTransformed.Add(v, new Vertex(v.VolumePosition, v.VolumeNormal)); Triangle NewTriangle = new Triangle(t.ID, VertexToTransformed[t.V0], VertexToTransformed[t.V1], VertexToTransformed[t.V2]); NewTriangles.Add(NewTriangle); OriginalToTransformed.Add(t, NewTriangle); TransformedToOriginal.Add(NewTriangle, t); } SurfaceMesh = new Mesh(); SurfaceMesh.Vertices.AddRange(VertexToTransformed.Values); SurfaceMesh.Triangles.AddRange(OriginalToTransformed.Values); SurfaceMesh.UpdateGraph(); SurfaceMesh.UpdateVertexIDs(); TurnUpsideUp(); // Don't update buffers because there is no OpenGL context yet. UpdateStats(); UpdatePlanarizationStats(); Membrane.DisplayedPatches.CollectionChanged += MembraneDisplayedPatches_CollectionChanged; Membrane.PointGroups.CollectionChanged += MembranePointGroups_CollectionChanged; MembranePointGroups_CollectionChanged(null, null); }
private static Triangle[] Polygonize(Vector3[] p, float[] val, float threshold) { // Determine the index into the edge table which // tells us which vertices are inside of the surface uint cubeindex = 0; if (val[0] < threshold) cubeindex |= 1; if (val[1] < threshold) cubeindex |= 2; if (val[2] < threshold) cubeindex |= 4; if (val[3] < threshold) cubeindex |= 8; if (val[4] < threshold) cubeindex |= 16; if (val[5] < threshold) cubeindex |= 32; if (val[6] < threshold) cubeindex |= 64; if (val[7] < threshold) cubeindex |= 128; // Cube is entirely in/out of the surface if (EdgeTable[cubeindex] == 0) return null; Vector3[] VertList = new Vector3[12]; // Find the vertices where the surface intersects the cube if ((EdgeTable[cubeindex] & 1) > 0) VertList[0] = VertexInterp(threshold, p[0], p[1], val[0], val[1]); if ((EdgeTable[cubeindex] & 2) > 0) VertList[1] = VertexInterp(threshold, p[1], p[2], val[1], val[2]); if ((EdgeTable[cubeindex] & 4) > 0) VertList[2] = VertexInterp(threshold, p[2], p[3], val[2], val[3]); if ((EdgeTable[cubeindex] & 8) > 0) VertList[3] = VertexInterp(threshold, p[3], p[0], val[3], val[0]); if ((EdgeTable[cubeindex] & 16) > 0) VertList[4] = VertexInterp(threshold, p[4], p[5], val[4], val[5]); if ((EdgeTable[cubeindex] & 32) > 0) VertList[5] = VertexInterp(threshold, p[5], p[6], val[5], val[6]); if ((EdgeTable[cubeindex] & 64) > 0) VertList[6] = VertexInterp(threshold, p[6], p[7], val[6], val[7]); if ((EdgeTable[cubeindex] & 128) > 0) VertList[7] = VertexInterp(threshold, p[7], p[4], val[7], val[4]); if ((EdgeTable[cubeindex] & 256) > 0) VertList[8] = VertexInterp(threshold, p[0], p[4], val[0], val[4]); if ((EdgeTable[cubeindex] & 512) > 0) VertList[9] = VertexInterp(threshold, p[1], p[5], val[1], val[5]); if ((EdgeTable[cubeindex] & 1024) > 0) VertList[10] = VertexInterp(threshold, p[2], p[6], val[2], val[6]); if ((EdgeTable[cubeindex] & 2048) > 0) VertList[11] = VertexInterp(threshold, p[3], p[7], val[3], val[7]); /* Create the triangle */ uint ntriang = 0; for (uint i = 0; TriTable[cubeindex, i] != -1; i += 3) ntriang++; Triangle[] Triangles = new Triangle[ntriang]; ntriang = 0; for (uint i = 0; TriTable[cubeindex, i] != -1; i += 3) { Triangles[ntriang] = new Triangle(0, new Vertex(VertList[TriTable[cubeindex, i]], Vector3.UnitX), new Vertex(VertList[TriTable[cubeindex, i + 1]], Vector3.UnitX), new Vertex(VertList[TriTable[cubeindex, i + 2]], Vector3.UnitX)); ntriang++; } return Triangles; }
public void UpdateProcessedGeometry(float offset) { ProcessedTriangles = new List<Triangle>(Triangles.Count); ProcessedTriangleMapping.Clear(); foreach (Triangle t in Triangles) { Vertex IV0 = new Vertex(t.Vertices[0].Position + t.Vertices[0].SmoothNormal * offset, new Vector3()); Vertex IV1 = new Vertex(t.Vertices[1].Position + t.Vertices[1].SmoothNormal * offset, new Vector3()); Vertex IV2 = new Vertex(t.Vertices[2].Position + t.Vertices[2].SmoothNormal * offset, new Vector3()); Triangle IT = new Triangle(t.ID, IV0, IV1, IV2) { IsVisible = t.IsVisible, Patch = t.Patch }; ProcessedTriangles.Add(IT); ProcessedTriangleMapping.Add(IT, t); } }
/// <summary> /// Implementation of Marching Cubes based on http://paulbourke.net/geometry/polygonise/ /// </summary> /// <param name="volume">Volume intensity values</param> /// <param name="dims">Volume dimensions</param> /// <param name="angpix">Angstrom per pixel</param> /// <param name="threshold">Isosurface threshold</param> /// <returns></returns> public static Mesh FromVolume(float[] volume, int3 dims, float angpix, float threshold) { Triangle[][] CellTriangles = new Triangle[volume.Length][]; unsafe { fixed (float* volumePtr = volume) for (int z = 0; z < dims.Z - 1; z++) { float zz = (z - dims.Z / 2) * angpix; for (int y = 0; y < dims.Y - 1; y++) { float yy = (y - dims.Y / 2) * angpix; for (int x = 0; x < dims.X - 1; x++) { float xx = (x - dims.X / 2) * angpix; Vector3[] p = new Vector3[8]; float[] val = new float[8]; p[0] = new Vector3(xx, yy, zz); p[1] = new Vector3(xx + angpix, yy, zz); p[2] = new Vector3(xx + angpix, yy + angpix, zz); p[3] = new Vector3(xx, yy + angpix, zz); p[4] = new Vector3(xx, yy, zz + angpix); p[5] = new Vector3(xx + angpix, yy, zz + angpix); p[6] = new Vector3(xx + angpix, yy + angpix, zz + angpix); p[7] = new Vector3(xx, yy + angpix, zz + angpix); val[0] = volumePtr[((z + 0) * dims.Y + (y + 0)) * dims.X + (x + 0)]; val[1] = volumePtr[((z + 0) * dims.Y + (y + 0)) * dims.X + (x + 1)]; val[2] = volumePtr[((z + 0) * dims.Y + (y + 1)) * dims.X + (x + 1)]; val[3] = volumePtr[((z + 0) * dims.Y + (y + 1)) * dims.X + (x + 0)]; val[4] = volumePtr[((z + 1) * dims.Y + (y + 0)) * dims.X + (x + 0)]; val[5] = volumePtr[((z + 1) * dims.Y + (y + 0)) * dims.X + (x + 1)]; val[6] = volumePtr[((z + 1) * dims.Y + (y + 1)) * dims.X + (x + 1)]; val[7] = volumePtr[((z + 1) * dims.Y + (y + 1)) * dims.X + (x + 0)]; CellTriangles[(z * dims.Y + y) * dims.X + x] = Polygonize(p, val, threshold); } } } } Mesh NewMesh = new Mesh(); for (int i = 0; i < CellTriangles.Length; i++) { if (CellTriangles[i] == null) continue; foreach (var tri in CellTriangles[i]) { NewMesh.Vertices.Add(tri.V0); NewMesh.Vertices.Add(tri.V1); NewMesh.Vertices.Add(tri.V2); tri.ID = NewMesh.Triangles.Count; NewMesh.Triangles.Add(tri); } } NewMesh.UpdateGraph(); NewMesh.UpdateVertexIDs(); return NewMesh; }