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"); }
/// <summary> /// Tries to search best candidate for remeshing. /// </summary> /// <param name="mesh">The mesh.</param> /// <param name="v1">The source vertex.</param> /// <param name="v2">The source vertex.</param> /// <param name="edge">The edge additional informations.</param> /// <returns>true when successful, false otherwise.</returns> private bool SearchBestCandidate(ref Mesh mesh, out Vertex v1, out Vertex v2, out Triangle.Edge edge) { var min = mesh.Triangles.Min(); if (min != null) { if (min.Edge12.Cost < min.Edge23.Cost) { if (min.Edge12.Cost < min.Edge31.Cost) { v1 = min.Vertex1; v2 = min.Vertex2; edge = min.Edge12; } else { v1 = min.Vertex3; v2 = min.Vertex1; edge = min.Edge31; } } else { if (min.Edge23.Cost < min.Edge31.Cost) { v1 = min.Vertex2; v2 = min.Vertex3; edge = min.Edge23; } else { v1 = min.Vertex3; v2 = min.Vertex1; edge = min.Edge31; } } return true; } v1 = null; v2 = null; edge = null; return false; }
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> /// Tries to search best candidate for remeshing. /// </summary> /// <param name="mesh">The mesh.</param> /// <param name="minimal">The minimal erase cost vertex.</param> /// <param name="toJoin">The vertex proposed to removal.</param> /// <returns>true when successful, false otherwise.</returns> public bool SearchBestCandidate(ref Mesh mesh, out Vertex minimal, out Vertex toJoin) { Vertex vertex = mesh.Vertices.Min(); Vertex neighbor = null; float distance = float.MaxValue; foreach (var v in vertex.Neighbors) { float current = Vector3.DistanceSquared(vertex.Position, v.Position); if (current < distance) { distance = current; neighbor = v; } } minimal = vertex; toJoin = neighbor; return neighbor != null; }
public void Process(ref Mesh mesh, int toRemove, IProgressListener listener = null) { Remesh(ref mesh, toRemove, listener); }
public void Process(ref Mesh mesh, double ratio, IProgressListener listener = null) { Process(ref mesh, (int)(mesh.Triangles.Count * (1.0 - ratio)), listener); }