/// <summary> /// Creates a new mesh where no vertices are shared. /// </summary> /// <param name="input"> /// The input mesh. /// </param> /// <returns> /// A new mesh. /// </returns> public static MeshGeometry3D NoSharedVertices(this MeshGeometry3D input) { var p = new Point3DCollection(); var ti = new Int32Collection(); Vector3DCollection n = null; if (input.Normals != null) { n = new Vector3DCollection(); } PointCollection tc = null; if (input.TextureCoordinates != null) { tc = new PointCollection(); } for (int i = 0; i < input.TriangleIndices.Count; i += 3) { int i0 = i; int i1 = i + 1; int i2 = i + 2; int index0 = input.TriangleIndices[i0]; int index1 = input.TriangleIndices[i1]; int index2 = input.TriangleIndices[i2]; var p0 = input.Positions[index0]; var p1 = input.Positions[index1]; var p2 = input.Positions[index2]; p.Add(p0); p.Add(p1); p.Add(p2); ti.Add(i0); ti.Add(i1); ti.Add(i2); if (n != null) { n.Add(input.Normals[index0]); n.Add(input.Normals[index1]); n.Add(input.Normals[index2]); } if (tc != null) { tc.Add(input.TextureCoordinates[index0]); tc.Add(input.TextureCoordinates[index1]); tc.Add(input.TextureCoordinates[index2]); } } #if SHARPDX return(new MeshGeometry3D { Positions = p, TriangleIndices = new SharpDX.Core.IntCollection(ti), Normals = n, TextureCoordinates = tc }); #else return(new MeshGeometry3D { Positions = p, TriangleIndices = ti, Normals = n, TextureCoordinates = tc }); #endif }
/// <summary> /// Calculates the normal vectors. /// </summary> /// <param name="positions"> /// The positions. /// </param> /// <param name="triangleIndices"> /// The triangle indices. /// </param> /// <returns> /// Collection of normal vectors. /// </returns> public static Vector3DCollection CalculateNormals(IList <Point3D> positions, IList <int> triangleIndices) { var normals = new Vector3DCollection(positions.Count); for (int i = 0; i < positions.Count; i++) { normals.Add(new Vector3D()); } for (int i = 0; i < triangleIndices.Count; i += 3) { int index0 = triangleIndices[i]; int index1 = triangleIndices[i + 1]; int index2 = triangleIndices[i + 2]; var p0 = positions[index0]; var p1 = positions[index1]; var p2 = positions[index2]; Vector3D u = p1 - p0; Vector3D v = p2 - p0; Vector3D w = SharedFunctions.CrossProduct(ref u, ref v); w.Normalize(); normals[index0] += w; normals[index1] += w; normals[index2] += w; } for (int i = 0; i < normals.Count; i++) { normals[i].Normalize(); } return(normals); }
/// <summary> /// Simplifies the specified mesh. /// </summary> /// <param name="mesh"> /// The mesh. /// </param> /// <param name="eps"> /// The tolerance. /// </param> /// <returns> /// A simplified mesh. /// </returns> public static MeshGeometry3D Simplify(this MeshGeometry3D mesh, DoubleOrSingle eps) { // Find common positions var dict = new Dictionary <int, int>(); // map position index to first occurence of same position for (int i = 0; i < mesh.Positions.Count; i++) { for (int j = i + 1; j < mesh.Positions.Count; j++) { if (dict.ContainsKey(j)) { continue; } var v = mesh.Positions[i] - mesh.Positions[j]; var l2 = SharedFunctions.LengthSquared(ref v); if (l2 < eps) { dict.Add(j, i); } } } var p = new Point3DCollection(); var ti = new Int32Collection(); // create new positions array var newIndex = new Dictionary <int, int>(); // map old index to new index for (int i = 0; i < mesh.Positions.Count; i++) { if (!dict.ContainsKey(i)) { newIndex.Add(i, p.Count); p.Add(mesh.Positions[i]); } } // Update triangle indices foreach (int index in mesh.TriangleIndices) { int j; ti.Add(dict.TryGetValue(index, out j) ? newIndex[j] : newIndex[index]); } #if SHARPDX var result = new MeshGeometry3D { Positions = p, TriangleIndices = new SharpDX.Core.IntCollection(ti), }; #else var result = new MeshGeometry3D { Positions = p, TriangleIndices = ti }; #endif return(result); }
/// <summary> /// Remove isolated(not connected to any triangles) vertices /// </summary> /// <param name="vertices"></param> /// <param name="triangles"></param> /// <param name="texture"></param> /// <param name="normals"></param> /// <param name="verticesOut"></param> /// <param name="trianglesOut"></param> /// <param name="textureOut"></param> /// <param name="normalOut"></param> public static void RemoveIsolatedVertices(IList <Point3D> vertices, IList <int> triangles, IList <Point> texture, IList <Vector3D> normals, out Point3DCollection verticesOut, out Int32Collection trianglesOut, out PointCollection textureOut, out Vector3DCollection normalOut) { verticesOut = null; trianglesOut = null; textureOut = null; normalOut = null; List <List <int> > tracking = new List <List <int> >(vertices.Count); Debug.WriteLine(string.Format("NumVert:{0}; NumTriangle:{1};", vertices.Count, triangles.Count)); for (int i = 0; i < vertices.Count; ++i) { tracking.Add(new List <int>()); } for (int i = 0; i < triangles.Count; ++i) { tracking[triangles[i]].Add(i); } List <int> vertToRemove = new List <int>(vertices.Count); for (int i = 0; i < vertices.Count; ++i) { if (tracking[i].Count == 0) { vertToRemove.Add(i); } } verticesOut = new Point3DCollection(vertices.Count - vertToRemove.Count); trianglesOut = new Int32Collection(triangles); if (texture != null) { textureOut = new PointCollection(vertices.Count - vertToRemove.Count); } if (normals != null) { normalOut = new Vector3DCollection(vertices.Count - vertToRemove.Count); } if (vertices.Count == vertToRemove.Count) { return; } int counter = 0; for (int i = 0; i < vertices.Count; ++i) { if (counter == vertToRemove.Count || i < vertToRemove[counter]) { verticesOut.Add(vertices[i]); if (texture != null) { textureOut.Add(texture[i]); } if (normals != null) { normalOut.Add(normals[i]); } foreach (var t in tracking[i]) { trianglesOut[t] -= counter; } } else { ++counter; } } Debug.WriteLine(string.Format("Remesh finished. Output NumVert:{0};", verticesOut.Count)); }