/// <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");
        }
Example #2
0
        /// <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");
        }
Example #3
0
        /// <summary>
        /// Updates vertex normals and face planes.
        /// </summary>
        public void Invalidate(IProgressListener listener = null, InvalidateFlags invalidate = InvalidateFlags.All)
        {
            if (invalidate.HasFlag(InvalidateFlags.Faces))
            {
                if (listener != null)
                {
                    listener.OnStarted("Invalidating mesh faces");
                }

                foreach (var face in m_Faces)
                {
                    var v0 = m_Vertices[face[0]].Position;
                    var v1 = m_Vertices[face[1]].Position;
                    var v2 = m_Vertices[face[2]].Position;
                    face.Plane = new Plane(v0, v1, v2);
                }

                if (listener != null)
                {
                    listener.OnComplete("Invalidating mesh faces");
                }
            }

            if (invalidate.HasFlag(InvalidateFlags.Vertices))
            {
                if (listener != null)
                {
                    listener.OnStarted("Invalidating mesh vertices");
                }

                int i = 0;
                foreach (var vertex in m_Vertices)
                {
                    foreach (var face in m_Faces)
                    {
                        if (face.HasVertex(vertex.Key))
                        {
                            vertex.Value.Normal += face.Plane.Normal;
                        }
                    }
                    if (listener != null)
                    {
                        listener.OnStep(++i, m_Vertices.Count);
                    }
                    vertex.Value.Normal.Normalize();
                }
                if (listener != null)
                {
                    listener.OnComplete("Invalidating mesh vertices");
                }
            }
        }
Example #4
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");
        }
        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");
        }
Example #6
0
        public void WriteMesh(ref Mesh mesh, IProgressListener listener = null)
        {
            long current = 0;
            long total   = mesh.Vertices.Count + mesh.Faces.Count;

            listener.OnStarted("Mesh write");

            foreach (var vertex in mesh.Vertices)
            {
                m_Writer.WriteLine(string.Format(
                                       CultureInfo.InvariantCulture,
                                       "v {0} {1} {2}",
                                       vertex.Value.Position.X.ToString("0.000000", CultureInfo.InvariantCulture),
                                       vertex.Value.Position.Y.ToString("0.000000", CultureInfo.InvariantCulture),
                                       vertex.Value.Position.Z.ToString("0.000000", CultureInfo.InvariantCulture)));

                ++current;

                if (listener != null)
                {
                    listener.OnStep(current, total);
                }
            }

            int count = 0;

            foreach (var face in mesh.Faces)
            {
                m_Writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "f {0} {1} {2}",
                                                 face[0], face[1], face[2]));

                ++count;
                ++current;

                if (listener != null)
                {
                    listener.OnStep(current, total);
                }
            }

            if (listener != null)
            {
                listener.OnComplete("Mesh write");
            }

            m_Writer.Close();
        }
Example #7
0
        /// <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");
            }
        }
Example #8
0
        /// <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");
            }
        }
Example #9
0
        /// <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();
        }
Example #10
0
        public virtual void Read(out Mesh mesh, IProgressListener listener = null)
        {
            mesh = new Mesh();

            Regex           r                    = new Regex(@" |//");
            NumberStyles    numberStyle          = NumberStyles.Float;
            IFormatProvider numberFormatProvider = CultureInfo.InvariantCulture;

            if (listener != null)
            {
                listener.OnStarted("Load mesh");
            }

            int indicesCount = 0;

            while (m_Reader.Peek() >= 0)
            {
                string line = m_Reader.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)
                        )
                    {
                        mesh.Vertices.Add(++indicesCount, new Vertex(new Vector3(x, y, z)));
                    }
                    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)
                            )
                        {
                            mesh.Faces.Add(new Triangle(f1, f2, f3));
                        }
                        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 (listener != null)
                {
                    listener.OnStep(
                        m_Reader.BaseStream.Position,
                        m_Reader.BaseStream.Length);
                }
            }

            if (listener != null)
            {
                listener.OnComplete("Mesh loaded successfully");
            }

            mesh.Invalidate(listener, Mesh.InvalidateFlags.Faces);
        }
Example #11
0
        /// <summary>
        /// Updates vertex normals and face planes.
        /// </summary>
        public void Invalidate(IProgressListener listener = null, InvalidateFlags invalidate = InvalidateFlags.All)
        {
            if (invalidate.HasFlag(InvalidateFlags.Faces))
            {
                if (listener != null)
                {
                    listener.OnStarted("Invalidating mesh faces");
                }

                foreach (var face in m_Faces)
                {
                    var v0 = m_Vertices[face[0]].Position;
                    var v1 = m_Vertices[face[1]].Position;
                    var v2 = m_Vertices[face[2]].Position;
                    face.Plane = new Plane(v0, v1, v2);

                }

                if (listener != null)
                {
                    listener.OnComplete("Invalidating mesh faces");
                }
            }

            if (invalidate.HasFlag(InvalidateFlags.Vertices))
            {
                if (listener != null)
                {
                    listener.OnStarted("Invalidating mesh vertices");
                }

                int i = 0;
                foreach (var vertex in m_Vertices)
                {
                    foreach (var face in m_Faces)
                    {
                        if (face.HasVertex(vertex.Key))
                        {
                            vertex.Value.Normal += face.Plane.Normal;
                        }
                    }
                    if (listener != null)
                    {
                        listener.OnStep(++i, m_Vertices.Count);
                    }
                    vertex.Value.Normal.Normalize();
                }
                if (listener != null)
                {
                    listener.OnComplete("Invalidating mesh vertices");
                }
            }
        }
Example #12
0
        public virtual void Read(out Mesh mesh, IProgressListener listener = null)
        {
            mesh = new Mesh();

            Regex r = new Regex(@" |//");
            NumberStyles numberStyle = NumberStyles.Float;
            IFormatProvider numberFormatProvider = CultureInfo.InvariantCulture;

            if (listener != null)
            {
                listener.OnStarted("Load mesh");
            }

            int indicesCount = 0;

            while (m_Reader.Peek() >= 0)
            {
                string line = m_Reader.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)
                                )
                            {
                                mesh.Vertices.Add(++indicesCount, new Vertex(new Vector3(x, y, z)));
                            }
                            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)
                                            )
                                        {
                                            mesh.Faces.Add(new Triangle(f1, f2, f3));
                                        }
                                        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 (listener != null)
                {
                    listener.OnStep(
                        m_Reader.BaseStream.Position,
                        m_Reader.BaseStream.Length);
                }
            }

            if (listener != null)
            {
                listener.OnComplete("Mesh loaded successfully");
            }

            mesh.Invalidate(listener, Mesh.InvalidateFlags.Faces);
        }
Example #13
0
        public void WriteMesh(ref Mesh mesh, IProgressListener listener = null)
        {
            long current = 0;
            long total = mesh.Vertices.Count + mesh.Faces.Count;

            listener.OnStarted("Mesh write");

            foreach (var vertex in mesh.Vertices)
            {
                m_Writer.WriteLine(string.Format(
                    CultureInfo.InvariantCulture,
                    "v {0} {1} {2}",
                    vertex.Value.Position.X.ToString("0.000000", CultureInfo.InvariantCulture),
                    vertex.Value.Position.Y.ToString("0.000000", CultureInfo.InvariantCulture),
                    vertex.Value.Position.Z.ToString("0.000000", CultureInfo.InvariantCulture)));

                ++current;

                if (listener != null)
                {
                    listener.OnStep(current, total);
                }
            }

            int count = 0;
            foreach (var face in mesh.Faces)
            {
                m_Writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "f {0} {1} {2}",
                    face[0], face[1], face[2]));

                ++count;
                ++current;

                if (listener != null)
                {
                    listener.OnStep(current, total);
                }
            }

            if (listener != null)
            {
                listener.OnComplete("Mesh write");
            }

            m_Writer.Close();
        }
Example #14
0
        /// <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();
        }
        private void Contract(int targetTriangles, IProgressListener listener = null)
        {
            SelectValidPairs();

            if (listener != null)
            {
                listener.OnStarted("Compacting");
            }

            int totalTriangles = m_Faces.Count - targetTriangles;
            int currentTriangle = 0;
            while (m_Faces.Count > targetTriangles)
            {
                if (listener != null)
                {
                    listener.OnStep(currentTriangle, totalTriangles);
                }
                ++currentTriangle;
                double minError = (double)int.MaxValue;

                //KeyValuePair<VertexPair, double> min;
                VertexPair minPair = new VertexPair() { First = 0, Second = 0 };

                foreach (KeyValuePair<VertexPair, double> e in m_Errors)
                {
                    if (e.Value < minError)
                    {
                        minError = e.Value;
                        minPair = e.Key;
                    }
                }

                Vector3 error;
                ComputeError(minPair.First, minPair.Second, out error);

#if false
                VertexSplit split = new VertexSplit();

                //var fv

                split.First.Position = m_Vertices[minPair.First].Position;
                split.Second.Position = m_Vertices[minPair.Second].Position;
                split.Target.Position = error;
                m_Splits.Add(split);
#endif
                var vertex = m_Vertices[minPair.First];
                vertex.Position = error;

                m_Quadrics[minPair.First] = m_Quadrics[minPair.First] + m_Quadrics[minPair.Second];

                for (int i = m_Faces.Count - 1; i != 0; )
                {
                    var face = m_Faces[i];

                    for (int j = 0; j < 3; ++j)
                    {
                        if (face[j] == minPair.Second)
                        {
                            if (face[0] == minPair.First || face[1] == minPair.First || face[2] == minPair.First)
                            {
                                m_Faces.Remove(face);
                            }
                            else
                            {
                                face[j] = minPair.First;
                            }
                            --i;
                            break;
                        }
                        else if (j == 2)
                        {
                            --i;
                        }
                    }
                }

                m_Vertices.Remove(minPair.Second);

                KeyValuePair<VertexPair, double> pair;

#if false
                for (int iter = m_Errors.Count - 1; iter != 0; )
                {
                    pair = m_Errors.ElementAt(iter);

                    if (pair.Key.First == minPair.Second && pair.Key.Second != minPair.First)
                    {
                        m_Errors.Remove(m_Errors.ElementAt(iter).Key);

                        m_Errors.Add(
                            new VertexPair() { First = Math.Min(minPair.First, pair.Key.Second), Second = Math.Max(minPair.First, pair.Key.Second) },
                            0.0);
                        --iter;
                    }
                    else if (pair.Key.Second == minPair.Second && pair.Key.First != minPair.First)
                    {
                        m_Errors.Remove(m_Errors.ElementAt(iter).Key);

                        m_Errors.Add(
                            new VertexPair() { First = Math.Min(minPair.First, pair.Key.First), Second = Math.Max(minPair.First, pair.Key.First) },
                            0.0);
                        --iter;
                    }
                    else
                    {
                        --iter;
                    }
                }
#else
                for (int it = 0; it < m_Errors.Count; ++it)
                {
                    pair = m_Errors.ElementAt(it);

                    if (pair.Key.First == minPair.Second && pair.Key.Second != minPair.First)
                    {
                        m_Errors.Remove(m_Errors.ElementAt(it).Key);

                        var key = new VertexPair()
                        {
                            First = Math.Min(minPair.First, pair.Key.Second),
                            Second = Math.Max(minPair.First, pair.Key.Second)
                        };

                        if (!m_Errors.ContainsKey(key))
                        {
                            m_Errors.Add(
                                key,
                                0.0);
                        }
                    }
                    else if (pair.Key.Second == minPair.Second && pair.Key.First != minPair.First)
                    {
                        m_Errors.Remove(m_Errors.ElementAt(it).Key);

                        var key = new VertexPair()
                        {
                            First = Math.Min(minPair.First, pair.Key.First),
                            Second = Math.Max(minPair.First, pair.Key.First)
                        };

                        if (!m_Errors.ContainsKey(key))
                        {
                            m_Errors.Add(
                                key,
                                0.0);
                        }
                    }
                }
#endif
                m_Errors.Remove(minPair);

                for (int it = 0; it < m_Errors.Count; ++it)
                {
                    var key = m_Errors.ElementAt(it).Key;

                    if (key.First == minPair.First)
                    {
                        m_Errors[key] = ComputeError(minPair.First, key.Second);
                    }

                    if (key.Second == minPair.First)
                    {
                        m_Errors[key] = ComputeError(minPair.First, key.First);
                    }
                }
                /*foreach (var e in m_Errors)
                {
                    var p = e.Key;
                    if (p.First == minPair.First)
                    {
                        m_Errors[p] = ComputeError(minPair.First, p.Second);
                    }

                    if (p.Second == minPair.First)
                    {
                        m_Errors[p] = ComputeError(minPair.First, p.First);
                    }
                }*/

            }
            if (listener != null)
            {
                listener.OnComplete("Compacting");
            }
        }
Example #16
0
        private void Contract(int targetTriangles, IProgressListener listener = null)
        {
            SelectValidPairs();

            if (listener != null)
            {
                listener.OnStarted("Compacting");
            }

            int totalTriangles  = m_Faces.Count - targetTriangles;
            int currentTriangle = 0;

            while (m_Faces.Count > targetTriangles)
            {
                if (listener != null)
                {
                    listener.OnStep(currentTriangle, totalTriangles);
                }
                ++currentTriangle;
                double minError = (double)int.MaxValue;

                //KeyValuePair<VertexPair, double> min;
                VertexPair minPair = new VertexPair()
                {
                    First = 0, Second = 0
                };

                foreach (KeyValuePair <VertexPair, double> e in m_Errors)
                {
                    if (e.Value < minError)
                    {
                        minError = e.Value;
                        minPair  = e.Key;
                    }
                }

                Vector3 error;
                ComputeError(minPair.First, minPair.Second, out error);

#if false
                VertexSplit split = new VertexSplit();

                //var fv

                split.First.Position  = m_Vertices[minPair.First].Position;
                split.Second.Position = m_Vertices[minPair.Second].Position;
                split.Target.Position = error;
                m_Splits.Add(split);
#endif
                var vertex = m_Vertices[minPair.First];
                vertex.Position = error;

                m_Quadrics[minPair.First] = m_Quadrics[minPair.First] + m_Quadrics[minPair.Second];

                for (int i = m_Faces.Count - 1; i != 0;)
                {
                    var face = m_Faces[i];

                    for (int j = 0; j < 3; ++j)
                    {
                        if (face[j] == minPair.Second)
                        {
                            if (face[0] == minPair.First || face[1] == minPair.First || face[2] == minPair.First)
                            {
                                m_Faces.Remove(face);
                            }
                            else
                            {
                                face[j] = minPair.First;
                            }
                            --i;
                            break;
                        }
                        else if (j == 2)
                        {
                            --i;
                        }
                    }
                }

                m_Vertices.Remove(minPair.Second);

                KeyValuePair <VertexPair, double> pair;

#if false
                for (int iter = m_Errors.Count - 1; iter != 0;)
                {
                    pair = m_Errors.ElementAt(iter);

                    if (pair.Key.First == minPair.Second && pair.Key.Second != minPair.First)
                    {
                        m_Errors.Remove(m_Errors.ElementAt(iter).Key);

                        m_Errors.Add(
                            new VertexPair()
                        {
                            First = Math.Min(minPair.First, pair.Key.Second), Second = Math.Max(minPair.First, pair.Key.Second)
                        },
                            0.0);
                        --iter;
                    }
                    else if (pair.Key.Second == minPair.Second && pair.Key.First != minPair.First)
                    {
                        m_Errors.Remove(m_Errors.ElementAt(iter).Key);

                        m_Errors.Add(
                            new VertexPair()
                        {
                            First = Math.Min(minPair.First, pair.Key.First), Second = Math.Max(minPair.First, pair.Key.First)
                        },
                            0.0);
                        --iter;
                    }
                    else
                    {
                        --iter;
                    }
                }
#else
                for (int it = 0; it < m_Errors.Count; ++it)
                {
                    pair = m_Errors.ElementAt(it);

                    if (pair.Key.First == minPair.Second && pair.Key.Second != minPair.First)
                    {
                        m_Errors.Remove(m_Errors.ElementAt(it).Key);

                        var key = new VertexPair()
                        {
                            First  = Math.Min(minPair.First, pair.Key.Second),
                            Second = Math.Max(minPair.First, pair.Key.Second)
                        };

                        if (!m_Errors.ContainsKey(key))
                        {
                            m_Errors.Add(
                                key,
                                0.0);
                        }
                    }
                    else if (pair.Key.Second == minPair.Second && pair.Key.First != minPair.First)
                    {
                        m_Errors.Remove(m_Errors.ElementAt(it).Key);

                        var key = new VertexPair()
                        {
                            First  = Math.Min(minPair.First, pair.Key.First),
                            Second = Math.Max(minPair.First, pair.Key.First)
                        };

                        if (!m_Errors.ContainsKey(key))
                        {
                            m_Errors.Add(
                                key,
                                0.0);
                        }
                    }
                }
#endif
                m_Errors.Remove(minPair);

                for (int it = 0; it < m_Errors.Count; ++it)
                {
                    var key = m_Errors.ElementAt(it).Key;

                    if (key.First == minPair.First)
                    {
                        m_Errors[key] = ComputeError(minPair.First, key.Second);
                    }

                    if (key.Second == minPair.First)
                    {
                        m_Errors[key] = ComputeError(minPair.First, key.First);
                    }
                }

                /*foreach (var e in m_Errors)
                 * {
                 *  var p = e.Key;
                 *  if (p.First == minPair.First)
                 *  {
                 *      m_Errors[p] = ComputeError(minPair.First, p.Second);
                 *  }
                 *
                 *  if (p.Second == minPair.First)
                 *  {
                 *      m_Errors[p] = ComputeError(minPair.First, p.First);
                 *  }
                 * }*/
            }
            if (listener != null)
            {
                listener.OnComplete("Compacting");
            }
        }