private void Remesh(ref Mesh mesh, int toRemove, IProgressListener progress = null) { if (!(toRemove > mesh.Triangles.Count && mesh.Triangles.Count > 10)) { throw new ArgumentOutOfRangeException("toRemove", toRemove, "Invalid triangle count"); } var vertices = mesh.Vertices; progress.OnStart("Started remeshing"); int totalVertices = mesh.Vertices.Count; Debug.Assert(toRemove > 0); Random random = new Random(); while (toRemove > 0) { //vertices.ran var element = vertices.ElementAt(random.Next(0, vertices.Count - 1)); mesh.JoinToNearestByDistance(element); toRemove -= 2; progress.OnProgress(toRemove, totalVertices); } progress.OnComplete("Ended remeshing"); }
/// <summary> /// Remeshes specified mesh. /// </summary> /// <param name="mesh">The mesh to remesh</param> /// <param name="toRemove">The number of triangles to remove.</param> /// <param name="progress">The progress listener.</param> private void Remesh(ref Mesh mesh, int toRemove, IProgressListener progress = null) { if (!(toRemove > mesh.Triangles.Count && mesh.Triangles.Count > 10)) { throw new ArgumentOutOfRangeException("toRemove", toRemove, "Invalid triangle count"); } progress.OnStart("Remeshing using AngleSum Error Metric"); var triangles = mesh.Triangles; var vertices = mesh.Vertices; if (triangles.Count <= toRemove) { progress.OnComplete("Failed. Too many triangles to remove"); } //int toRemove = (int)((m_Removed) * triangles.Count); int triangleLimit = triangles.Count - toRemove; foreach (var v in vertices) { UpdateVertexCost(v); } #if false // Adding mesh border penalty. foreach (var v in vertices) { // Border vertices has no more that 5 neighbors if (v.Neighbors.Count <= 4) { v.Cost += 1.0; } } #endif int index = 0; while (triangles.Count > triangleLimit) { var min = mesh.Vertices.Min(); if (mesh.JoinToNearestByCost(min, Mesh.JoinPositionType.Source)) { UpdateVertexCost(min); UpdateVertexNeighborsCost(min); progress.OnProgress(vertices.Count, triangles.Count); index += 2; } } progress.OnComplete("End of remeshing using AngleSum Error Metric"); }
public void Remesh(ref Mesh mesh, IProgressListener progress = null) { var triangles = mesh.Triangles; var vertices = mesh.Vertices; // Compute K matrices for initial triangles. foreach (var t in triangles) { t.UpdateGeometricData(); t.Tag = new ErrorMetric(t); } // Compute Q for intiial vertices. foreach (var v in vertices) { ComputeErrorMetricForVertex(v); } // Compute initial edge QEM-s foreach (var t in triangles) { ComputeErrorMetricForEdges(t); } foreach (var t in triangles) { ComputeEdgeCost(t); } // Compute number of triangles after we stop int toRemove = (int)((m_Removed) * triangles.Count); int triangleLimit = triangles.Count - toRemove; #if TRACE_NANS int nansCount = 0; #endif int index = 0; while (triangleLimit < triangles.Count) { Vertex v1, v2; Triangle.Edge edge; if (SearchBestCandidate(ref mesh, out v1, out v2, out edge)) { if (edge != null) { ErrorMetric em = (ErrorMetric)edge.Tag; Vector3 v = em.ProposedPoint; #if false if (v.IsNaN()) { #if TRACE_NANS ++nansCount; #endif v = Vector3Extension.Mean(v1.Position, v2.Position); } #endif if (mesh.JoinVertices(v1, v2, v)) { // V1, since v2 is removed from now. UpdateVertexNeighbors(v1); } progress.OnProgress(index, toRemove); index += 2; } else { Trace.WriteLine("If you see this message more than once per second, I can't find any matching edge"); } } } #if TRACE_NANS Trace.WriteLine(string.Format("NaNs count: {0}", nansCount)); #endif }
/// <summary> /// Reads raw mesh. /// </summary> /// <param name="vertices">The list of the vertices.</param> /// <param name="indices">The list of the indices.</param> /// <param name="progress">The optional progress listener.</param> public void ReadMesh(out List <Vertex> vertices, out List <int> indices, IProgressListener progress = null) { vertices = new List <Vertex>(); indices = new List <int>(); Regex r = new Regex(@" |//"); NumberStyles numberStyle = NumberStyles.Float; IFormatProvider numberFormatProvider = CultureInfo.InvariantCulture; progress.OnStart("Loading mesh started..."); while (inputReader.Peek() >= 0) { string line = inputReader.ReadLine(); String[] elements = r.Split(line); // List<Vertex> normals; switch (elements[0]) { case "v": { float x, y, z; if ( float.TryParse(elements[1], numberStyle, numberFormatProvider, out x) && float.TryParse(elements[2], numberStyle, numberFormatProvider, out y) && float.TryParse(elements[3], numberStyle, numberFormatProvider, out z) ) { Vertex w = new Vertex(new Vector3(x, y, z)); vertices.Add(w); } else { Trace.WriteLine(line); } break; } case "f": { int f1, f2, f3; int f1Index = 1; int f2Index = 2; int f3Index = 3; switch (elements.Length) { case 7: { //normal indexes in elements[2],elements[4] and elements[6] are ignored; f1Index = 1; f2Index = 3; f3Index = 5; goto case 4; } case 4: { if ( int.TryParse(elements[f1Index], numberStyle, numberFormatProvider, out f1) && int.TryParse(elements[f2Index], numberStyle, numberFormatProvider, out f2) && int.TryParse(elements[f3Index], numberStyle, numberFormatProvider, out f3) ) { indices.Add(f1 - 1); indices.Add(f2 - 1); indices.Add(f3 - 1); } else { Trace.WriteLine(line); throw new NotImplementedException("Only triangles are Implemented. Faces in file are not a triangles.That is bad:("); } } break; default: Trace.WriteLine("Invalid number of components"); break; } break; } case "vn": { break; } default: Trace.WriteLine("Unknown obj specifier."); break; } if (progress != null) { progress.OnProgress( inputReader.BaseStream.Position, inputReader.BaseStream.Length); } } if (progress != null) { progress.OnComplete("Mesh loaded successfully"); } }
/// <summary> /// Reads raw mesh. /// </summary> /// <param name="vertices">The list of the vertices.</param> /// <param name="indices">The list of the indices.</param> /// <param name="progress">The optional progress listener.</param> public void ReadMesh(out List<Vertex> vertices, out List<int> indices, IProgressListener progress = null) { vertices = new List<Vertex>(); indices = new List<int>(); Regex r = new Regex(@" |//"); NumberStyles numberStyle = NumberStyles.Float; IFormatProvider numberFormatProvider = CultureInfo.InvariantCulture; progress.OnStart("Loading mesh started..."); while (inputReader.Peek() >= 0) { string line = inputReader.ReadLine(); String[] elements = r.Split(line); // List<Vertex> normals; switch (elements[0]) { case "v": { float x, y, z; if ( float.TryParse(elements[1], numberStyle, numberFormatProvider, out x) && float.TryParse(elements[2], numberStyle, numberFormatProvider, out y) && float.TryParse(elements[3], numberStyle, numberFormatProvider, out z) ) { Vertex w = new Vertex(new Vector3(x, y, z)); vertices.Add(w); } else { Trace.WriteLine(line); } break; } case "f": { int f1, f2, f3; int f1Index = 1; int f2Index = 2; int f3Index = 3; switch (elements.Length) { case 7: { //normal indexes in elements[2],elements[4] and elements[6] are ignored; f1Index = 1; f2Index = 3; f3Index = 5; goto case 4; } case 4: { if ( int.TryParse(elements[f1Index], numberStyle, numberFormatProvider, out f1) && int.TryParse(elements[f2Index], numberStyle, numberFormatProvider, out f2) && int.TryParse(elements[f3Index], numberStyle, numberFormatProvider, out f3) ) { indices.Add(f1 -1); indices.Add(f2 -1); indices.Add(f3 -1); } else { Trace.WriteLine(line); throw new NotImplementedException("Only triangles are Implemented. Faces in file are not a triangles.That is bad:("); } } break; default: Trace.WriteLine("Invalid number of components"); break; } break; } case "vn": { break; } default: Trace.WriteLine("Unknown obj specifier."); break; } if (progress != null) { progress.OnProgress( inputReader.BaseStream.Position, inputReader.BaseStream.Length); } } if (progress != null) { progress.OnComplete("Mesh loaded successfully"); } }
public void Remesh(ref Mesh mesh, IProgressListener progress = null) { var triangles = mesh.Triangles; var vertices = mesh.Vertices; // Compute K matrices for initial triangles. foreach (var t in triangles) { t.UpdateGeometricData(); t.Tag = new ErrorMetric(t); } // Compute Q for intiial vertices. foreach (var v in vertices) { ComputeErrorMetricForVertex(v); } // Compute initial edge QEM-s foreach (var t in triangles) { ComputeErrorMetricForEdges(t); } foreach (var t in triangles) { ComputeEdgeCost(t); } foreach (var v in vertices) { v.Cost = 0.0; foreach (var t in v.Triangles) { v.Cost += Math.Max(Math.Max(t.Edge12.Cost, t.Edge23.Cost), t.Edge31.Cost); } } // Compute number of triangles after we stop int toRemove = (int)((m_Removed) * triangles.Count); int triangleLimit = triangles.Count - toRemove; #if TRACE_NANS int nansCount = 0; #endif int index = 0; for (int i = 0; (i < m_Removed) && (2 * m_Removed < triangles.Count); i += 2) { Vertex v1, v2; Triangle.Edge edge; if (SearchBestCandidate(ref mesh, out v1, out v2, out edge)) { if (edge != null) { ErrorMetric em = (ErrorMetric)edge.Tag; Vector3 v = em.ProposedPoint; #if false if (v.IsNaN()) { #if TRACE_NANS ++nansCount; #endif v = Vector3Extension.Mean(v1.Position, v2.Position); } #endif if (mesh.JoinVertices(v1, v2, v)) { // V1, since v2 is removed from now. UpdateVertexNeighbors(v1); } progress.OnProgress(index, toRemove); index += 2; } else { Trace.WriteLine("If you see this message more than once per second, I can't find any matching edge"); } } } #if TRACE_NANS Trace.WriteLine(string.Format("NaNs count: {0}", nansCount)); #endif }
/// <summary> /// Writes raw mesh to stream. /// </summary> /// <param name="vertices">The list of the vertices.</param> /// <param name="indices">The list of the indices.</param> /// <param name="progress">The optional progress listener.</param> public void WriteMesh(ref List<Vertex> vertices, ref List<int> indices, IProgressListener progress = null) { long current = 0; long total = vertices.Count + indices.Count; progress.OnStart("Mesh writing started..."); foreach (var vertex in vertices) { m_Writer.WriteLine(string.Format( CultureInfo.InvariantCulture, "v {0} {1} {2}", vertex.Position.X.ToString("0.000000", CultureInfo.InvariantCulture), vertex.Position.Y.ToString("0.000000", CultureInfo.InvariantCulture), vertex.Position.Z.ToString("0.000000", CultureInfo.InvariantCulture))); ++current; if (progress != null) { progress.OnProgress(current, total); } } int count = 0; foreach (var index in indices) { switch (count % 3) { case 0: { m_Writer.Write(string.Format(CultureInfo.InvariantCulture, "f {0} ", index + 1)); break; } case 1: { m_Writer.Write(string.Format(CultureInfo.InvariantCulture, "{0} ", index + 1)); break; } case 2: { m_Writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0}", index + 1)); break; } default: { Trace.WriteLine("Not supported"); break; } } ++count; ++current; if (progress != null) { progress.OnProgress(current, total); } } if (progress != null) { progress.OnComplete("Mesh writing complete"); } m_Writer.Close(); }
/// <summary> /// Writes raw mesh to stream. /// </summary> /// <param name="vertices">The list of the vertices.</param> /// <param name="indices">The list of the indices.</param> /// <param name="progress">The optional progress listener.</param> public void WriteMesh(ref List <Vertex> vertices, ref List <int> indices, IProgressListener progress = null) { long current = 0; long total = vertices.Count + indices.Count; progress.OnStart("Mesh writing started..."); foreach (var vertex in vertices) { m_Writer.WriteLine(string.Format( CultureInfo.InvariantCulture, "v {0} {1} {2}", vertex.Position.X.ToString("0.000000", CultureInfo.InvariantCulture), vertex.Position.Y.ToString("0.000000", CultureInfo.InvariantCulture), vertex.Position.Z.ToString("0.000000", CultureInfo.InvariantCulture))); ++current; if (progress != null) { progress.OnProgress(current, total); } } int count = 0; foreach (var index in indices) { switch (count % 3) { case 0: { m_Writer.Write(string.Format(CultureInfo.InvariantCulture, "f {0} ", index + 1)); break; } case 1: { m_Writer.Write(string.Format(CultureInfo.InvariantCulture, "{0} ", index + 1)); break; } case 2: { m_Writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0}", index + 1)); break; } default: { Trace.WriteLine("Not supported"); break; } } ++count; ++current; if (progress != null) { progress.OnProgress(current, total); } } if (progress != null) { progress.OnComplete("Mesh writing complete"); } m_Writer.Close(); }