/// <summary> /// creates a mesh from the current volume and tries to save it to a file /// </summary> /// <param name="volume">the volume</param> /// <param name="pkdp">the data package the mesh origined from</param> /// <param name="flipAxes">should achses be flipped?</param> static void exportMesh(ColorReconstruction volume, KinectDataPackage pkdp, bool flipAxes) { ColorMesh mesh = volume.CalculateMesh(1); Microsoft.Win32.SaveFileDialog dialog = new Microsoft.Win32.SaveFileDialog(); dialog.FileName = "KinectFusionMesh_" + pkdp.usedConfig.name + DateTime.UtcNow.ToShortDateString() + ".stl"; dialog.Filter = "STL Mesh Files|*.stl|All Files|*.*"; if (true == dialog.ShowDialog()) { using (BinaryWriter writer = new BinaryWriter(dialog.OpenFile())) { if (null == mesh || null == writer) { return; } var vertices = mesh.GetVertices(); var normals = mesh.GetNormals(); var indices = mesh.GetTriangleIndexes(); // Check mesh arguments if (0 == vertices.Count || 0 != vertices.Count % 3 || vertices.Count != indices.Count) { throw new Exception("Invalid Mesh Arguments"); } char[] header = new char[80]; writer.Write(header); // Write number of triangles int triangles = vertices.Count / 3; writer.Write(triangles); // Sequentially write the normal, 3 vertices of the triangle and attribute, for each triangle for (int i = 0; i < triangles; i++) { // Write normal var normal = normals[i * 3]; writer.Write(normal.X); writer.Write(flipAxes ? -normal.Y : normal.Y); writer.Write(flipAxes ? -normal.Z : normal.Z); // Write vertices for (int j = 0; j < 3; j++) { var vertex = vertices[(i * 3) + j]; writer.Write(vertex.X); writer.Write(flipAxes ? -vertex.Y : vertex.Y); writer.Write(flipAxes ? -vertex.Z : vertex.Z); } ushort attribute = 0; writer.Write(attribute); } } } }
[ExcludeFromCodeCoverage] //Cannot test this as it requires a Kinect ColorMesh which is dependent on the Kinect API: //you can't construct this yourself public static CVMesh ConvertToMesh(ColorMesh mesh) { CVMesh m = new CVMesh(); m.Colors.AddRange(mesh.GetColors()); m.Normals.AddRange(mesh.GetNormals()); m.TriangleIndeces.AddRange(mesh.GetTriangleIndexes()); m.Vertices.AddRange(mesh.GetVertices()); return(m); }
/// <summary> /// Save mesh in binary .STL file /// </summary> /// <param name="mesh">Calculated mesh object</param> /// <param name="writer">Binary file writer</param> /// <param name="flipAxes">Flag to determine whether the Y and Z values are flipped on save, /// default should be true.</param> public static void SaveBinaryStlMesh(ColorMesh mesh, BinaryWriter writer, bool flipAxes) { if (null == mesh || null == writer) { return; } var vertices = mesh.GetVertices(); var normals = mesh.GetNormals(); var indices = mesh.GetTriangleIndexes(); // Check mesh arguments if (0 == vertices.Count || 0 != vertices.Count % 3 || vertices.Count != indices.Count) { throw new ArgumentException(Properties.Resources.InvalidMeshArgument); } char[] header = new char[80]; writer.Write(header); // Write number of triangles int triangles = vertices.Count / 3; writer.Write(triangles); // Sequentially write the normal, 3 vertices of the triangle and attribute, for each triangle for (int i = 0; i < triangles; i++) { // Write normal var normal = normals[i * 3]; writer.Write(normal.X); writer.Write(flipAxes ? -normal.Y : normal.Y); writer.Write(flipAxes ? -normal.Z : normal.Z); // Write vertices for (int j = 0; j < 3; j++) { var vertex = vertices[(i * 3) + j]; writer.Write(vertex.X); writer.Write(flipAxes ? -vertex.Y : vertex.Y); writer.Write(flipAxes ? -vertex.Z : vertex.Z); } ushort attribute = 0; writer.Write(attribute); } }
/// <summary> /// Save mesh in ASCII WaveFront .OBJ file /// </summary> /// <param name="mesh">Calculated mesh object</param> /// <param name="writer">The text writer</param> /// <param name="flipAxes">Flag to determine whether the Y and Z values are flipped on save, /// default should be true.</param> public static void SaveAsciiObjMesh(ColorMesh mesh, TextWriter writer, bool flipAxes) { if (null == mesh || null == writer) { return; } try { var vertices = mesh.GetVertices(); var normals = mesh.GetNormals(); var indices = mesh.GetTriangleIndexes(); // Check mesh arguments if (0 == vertices.Count || 0 != vertices.Count % 3 || vertices.Count != indices.Count) { throw new ArgumentException(Properties.Resources.InvalidMeshArgument); } // Write the header lines writer.WriteLine("#"); writer.WriteLine("# OBJ file created by Microsoft Kinect Fusion"); writer.WriteLine("#"); // Sequentially write the 3 vertices of the triangle, for each triangle for (int i = 0; i < vertices.Count; i++) { var vertex = vertices[i]; string vertexString = "v " + vertex.X.ToString(CultureInfo.InvariantCulture) + " "; if (flipAxes) { vertexString += (-vertex.Y).ToString(CultureInfo.InvariantCulture) + " " + (-vertex.Z).ToString(CultureInfo.InvariantCulture); } else { vertexString += vertex.Y.ToString(CultureInfo.InvariantCulture) + " " + vertex.Z.ToString(CultureInfo.InvariantCulture); } writer.WriteLine(vertexString); } // Sequentially write the 3 normals of the triangle, for each triangle for (int i = 0; i < normals.Count; i++) { var normal = normals[i]; string normalString = "vn " + normal.X.ToString(CultureInfo.InvariantCulture) + " "; if (flipAxes) { normalString += (-normal.Y).ToString(CultureInfo.InvariantCulture) + " " + (-normal.Z).ToString(CultureInfo.InvariantCulture); } else { normalString += normal.Y.ToString(CultureInfo.InvariantCulture) + " " + normal.Z.ToString(CultureInfo.InvariantCulture); } writer.WriteLine(normalString); } // Sequentially write the 3 vertex indices of the triangle face, for each triangle // Note this is typically 1-indexed in an OBJ file when using absolute referencing! for (int i = 0; i < vertices.Count / 3; i++) { string baseIndex0 = ((i * 3) + 1).ToString(CultureInfo.InvariantCulture); string baseIndex1 = ((i * 3) + 2).ToString(CultureInfo.InvariantCulture); string baseIndex2 = ((i * 3) + 3).ToString(CultureInfo.InvariantCulture); string faceString = "f " + baseIndex0 + "//" + baseIndex0 + " " + baseIndex1 + "//" + baseIndex1 + " " + baseIndex2 + "//" + baseIndex2; writer.WriteLine(faceString); } } catch { } }
/// <summary> /// Save mesh in binary .STL file /// </summary> /// <param name="mesh">Calculated mesh object</param> /// <param name="writer">Binary file writer</param> /// <param name="flipAxes">Flag to determine whether the Y and Z values are flipped on save, /// default should be true.</param> public static void SaveBinaryStlMesh(ColorMesh mesh, BinaryWriter writer, bool flipAxes) { if (null == mesh || null == writer) { return; } var vertices = mesh.GetVertices(); var normals = mesh.GetNormals(); var indices = mesh.GetTriangleIndexes(); // Check mesh arguments if (0 == vertices.Count || 0 != vertices.Count % 3 || vertices.Count != indices.Count) { throw new ArgumentException("Invalid Mesh"); } char[] header = new char[80]; writer.Write(header); // Write number of triangles int triangles = vertices.Count / 3; writer.Write(triangles); // Sequentially write the normal, 3 vertices of the triangle and attribute, for each triangle for (int i = 0; i < triangles; i++) { // Write normal var normal = normals[i * 3]; writer.Write(normal.X); writer.Write(flipAxes ? -normal.Y : normal.Y); writer.Write(flipAxes ? -normal.Z : normal.Z); // Write vertices for (int j = 0; j < 3; j++) { var vertex = vertices[(i * 3) + j]; writer.Write(vertex.X); writer.Write(flipAxes ? -vertex.Y : vertex.Y); writer.Write(flipAxes ? -vertex.Z : vertex.Z); } ushort attribute = 0; writer.Write(attribute); } }
/// <summary> /// Save mesh in ASCII WaveFront .OBJ file /// </summary> /// <param name="mesh">Calculated mesh object</param> /// <param name="writer">The text writer</param> /// <param name="flipAxes">Flag to determine whether the Y and Z values are flipped on save, /// default should be true.</param> public static void SaveAsciiObjMesh(ColorMesh mesh, TextWriter writer, bool flipAxes) { if (null == mesh || null == writer) { return; } var vertices = mesh.GetVertices(); var normals = mesh.GetNormals(); var indices = mesh.GetTriangleIndexes(); // Check mesh arguments if (0 == vertices.Count || 0 != vertices.Count % 3 || vertices.Count != indices.Count) { throw new ArgumentException(); } // Write the header lines writer.WriteLine("#"); writer.WriteLine("# OBJ file created by Microsoft Kinect Fusion"); writer.WriteLine("#"); // Sequentially write the 3 vertices of the triangle, for each triangle for (int i = 0; i < vertices.Count; i++) { var vertex = vertices[i]; string vertexString = "v " + vertex.X.ToString(CultureInfo.InvariantCulture) + " "; if (flipAxes) { vertexString += (-vertex.Y).ToString(CultureInfo.InvariantCulture) + " " + (-vertex.Z).ToString(CultureInfo.InvariantCulture); } else { vertexString += vertex.Y.ToString(CultureInfo.InvariantCulture) + " " + vertex.Z.ToString(CultureInfo.InvariantCulture); } writer.WriteLine(vertexString); } // Sequentially write the 3 normals of the triangle, for each triangle for (int i = 0; i < normals.Count; i++) { var normal = normals[i]; string normalString = "vn " + normal.X.ToString(CultureInfo.InvariantCulture) + " "; if (flipAxes) { normalString += (-normal.Y).ToString(CultureInfo.InvariantCulture) + " " + (-normal.Z).ToString(CultureInfo.InvariantCulture); } else { normalString += normal.Y.ToString(CultureInfo.InvariantCulture) + " " + normal.Z.ToString(CultureInfo.InvariantCulture); } writer.WriteLine(normalString); } // Sequentially write the 3 vertex indices of the triangle face, for each triangle // Note this is typically 1-indexed in an OBJ file when using absolute referencing! for (int i = 0; i < vertices.Count / 3; i++) { string baseIndex0 = ((i * 3) + 1).ToString(CultureInfo.InvariantCulture); string baseIndex1 = ((i * 3) + 2).ToString(CultureInfo.InvariantCulture); string baseIndex2 = ((i * 3) + 3).ToString(CultureInfo.InvariantCulture); string faceString = "f " + baseIndex0 + "//" + baseIndex0 + " " + baseIndex1 + "//" + baseIndex1 + " " + baseIndex2 + "//" + baseIndex2; writer.WriteLine(faceString); } }
public void Update(IPluginIO pin, DX11RenderContext context) { if (!this.FTextureOutput[0].Contains(context)) { this.FTextureOutput[0][context] = new DX11DynamicTexture2D(context, this.width, this.height, SlimDX.DXGI.Format.R8G8B8A8_UNorm); this.FPCOut[0][context] = new DX11DynamicStructuredBuffer <float>(context, 640 * 480 * 6); } if (this.FInvalidate) { fixed(int *f = &this.pic[0]) { IntPtr ptr = new IntPtr(f); this.FTextureOutput[0][context].WriteData(ptr, this.width * this.height * 4); } /*fixed (float* f = &this.piccloud[0]) * {* * IntPtr ptr = new IntPtr(f);*/ DX11DynamicStructuredBuffer <float> db = (DX11DynamicStructuredBuffer <float>) this.FPCOut[0][context]; db.WriteData(this.piccloud); //} this.FInvalidate = false; } if (this.FInVoxels[0]) { if (this.FOutVoxels[0].Contains(context)) { this.FOutVoxels[0].Dispose(context); } short[] data = new short[this.VoxelResolutionX * this.VoxelResolutionY * this.VoxelResolutionZ]; this.colorVolume.ExportVolumeBlock(0, 0, 0, this.VoxelResolutionX, this.VoxelResolutionY, this.VoxelResolutionZ, 1, data); DX11DynamicStructuredBuffer <int> b = new DX11DynamicStructuredBuffer <int>(context, this.VoxelResolutionX * this.VoxelResolutionY * this.VoxelResolutionZ); int[] idata = new int[this.VoxelResolutionX * this.VoxelResolutionY * this.VoxelResolutionZ]; for (int i = 0; i < this.VoxelResolutionX * this.VoxelResolutionY * this.VoxelResolutionZ; i++) { idata[i] = data[i]; } b.WriteData(idata); this.FOutVoxels[0][context] = b; } if (this.FInExport[0]) { if (this.FGeomOut[0].Contains(context)) { this.FGeomOut[0].Dispose(context); } if (this.colorVolume != null) { ColorMesh m = this.colorVolume.CalculateMesh(this.FInGeomVoxelStep[0]); DX11IndexedGeometry geom = new DX11IndexedGeometry(context); ReadOnlyCollection <int> inds = m.GetTriangleIndexes(); DataStream ds = new DataStream(inds.Count * 4, true, true); ds.WriteRange <int>(inds.ToArray()); ds.Position = 0; DX11IndexBuffer ibo = new DX11IndexBuffer(context, ds, false, true); ReadOnlyCollection <Microsoft.Kinect.Toolkit.Fusion.Vector3> pos = m.GetVertices(); ReadOnlyCollection <Microsoft.Kinect.Toolkit.Fusion.Vector3> norm = m.GetNormals(); ReadOnlyCollection <int> col = m.GetColors(); DataStream dsv = new DataStream(Pos3Norm3Vertex.VertexSize * pos.Count, true, true); SlimDX.Vector3 bmin = new SlimDX.Vector3(float.MaxValue, float.MaxValue, float.MaxValue); SlimDX.Vector3 bmax = new SlimDX.Vector3(float.MinValue, float.MinValue, float.MinValue); for (int i = 0; i < pos.Count; i++) { Microsoft.Kinect.Toolkit.Fusion.Vector3 p = pos[i]; Microsoft.Kinect.Toolkit.Fusion.Vector3 n = norm[i]; dsv.Write <Microsoft.Kinect.Toolkit.Fusion.Vector3>(p); dsv.Write <Microsoft.Kinect.Toolkit.Fusion.Vector3>(n); dsv.Write <int>(col[i]); if (p.X < bmin.X) { bmin.X = p.X; } if (p.Y < bmin.Y) { bmin.Y = p.Y; } if (p.Z < bmin.Z) { bmin.Z = p.Z; } if (p.X > bmax.X) { bmax.X = p.X; } if (p.Y > bmax.Y) { bmax.Y = p.Y; } if (p.Z > bmax.Z) { bmax.Z = p.Z; } } geom.IndexBuffer = ibo; geom.HasBoundingBox = true; geom.InputLayout = FusionColoredVertex.Layout; geom.Topology = SlimDX.Direct3D11.PrimitiveTopology.TriangleList; geom.VertexSize = FusionColoredVertex.VertexSize; geom.VertexBuffer = BufferHelper.CreateVertexBuffer(context, dsv, false, true); geom.VerticesCount = pos.Count; geom.BoundingBox = new BoundingBox(bmin, bmax); this.FGeomOut[0][context] = geom; m.Dispose(); } } }
public void Write(ColorMesh mesh) { if (mesh == null) { throw new ArgumentNullException("mesh"); } var vertices = mesh.GetVertices(); var normals = mesh.GetNormals(); var indices = mesh.GetTriangleIndexes(); // Check mesh arguments if (vertices.Count == 0 || vertices.Count % 3 != 0 || vertices.Count != indices.Count) { throw new ArgumentException("Invalid mesh"); } logger.Trace("Start writing mesh to {0}", this.fileName); // Write the header lines this.textWriter.WriteLine("#"); this.textWriter.WriteLine("# OBJ file created by Arcinect © Wu Yuntao 2015"); this.textWriter.WriteLine("#"); // Sequentially write the 3 vertices of the triangle, for each triangle foreach (var vertex in vertices) { var vertexString = string.Format("v {0} {1} {2}", vertex.X.ToString(CultureInfo.InvariantCulture), vertex.Y.ToString(CultureInfo.InvariantCulture), vertex.Z.ToString(CultureInfo.InvariantCulture)); this.textWriter.WriteLine(vertexString); } // Sequentially write the 3 normals of the triangle, for each triangle foreach (var normal in normals) { var normalString = string.Format("vn {0} {1} {2}", normal.X.ToString(CultureInfo.InvariantCulture), normal.Y.ToString(CultureInfo.InvariantCulture), normal.Z.ToString(CultureInfo.InvariantCulture)); this.textWriter.WriteLine(normalString); } // Sequentially write the 3 vertex indices of the triangle face, for each triangle // Note this is typically 1-indexed in an OBJ file when using absolute referencing! for (int i = 0; i < vertices.Count / 3; i++) { var index = vertexCount + i * 3; var faceString = string.Format("f {0}//{0} {1}//{1} {2}//{2}", (index + 1).ToString(CultureInfo.InvariantCulture), (index + 2).ToString(CultureInfo.InvariantCulture), (index + 3).ToString(CultureInfo.InvariantCulture)); this.textWriter.WriteLine(faceString); } this.vertexCount += vertices.Count; logger.Trace("Finish writing mesh to {0}", this.fileName); }