Пример #1
0
        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");
        }
Пример #3
0
        /// <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;
        }
Пример #4
0
        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);
 }