Exemplo n.º 1
0
        /// <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
        }
Exemplo n.º 2
0
        /// <summary>
        /// Finds all edges in the mesh (each edge is only included once).
        /// </summary>
        /// <param name="mesh">
        /// A mesh geometry.
        /// </param>
        /// <returns>
        /// The edge indices (minimum index first).
        /// </returns>
        public static Int32Collection FindEdges(this MeshGeometry3D mesh)
        {
            var edges = new Int32Collection();
            var dict  = new HashSet <ulong>();

            for (int i = 0; i < mesh.TriangleIndices.Count / 3; i++)
            {
                int i0 = i * 3;
                for (int j = 0; j < 3; j++)
                {
                    int   index0   = mesh.TriangleIndices[i0 + j];
                    int   index1   = mesh.TriangleIndices[i0 + ((j + 1) % 3)];
                    int   minIndex = Math.Min(index0, index1);
                    int   maxIndex = Math.Max(index1, index0);
                    ulong key      = CreateKey((uint)minIndex, (uint)maxIndex);
                    if (!dict.Contains(key))
                    {
                        edges.Add(minIndex);
                        edges.Add(maxIndex);
                        dict.Add(key);
                    }
                }
            }

            return(edges);
        }
Exemplo n.º 3
0
        /// <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);
        }
Exemplo n.º 4
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public MeshGeometry3D GetMesh()
        {
            var pos  = new Point3DCollection(vertices.Select(x => new Point3D(x.p.X, x.p.Y, x.p.Z)));
            var tris = new Int32Collection(triangles.Count * 3);

            foreach (var tri in triangles)
            {
                tris.Add(tri.v[0]);
                tris.Add(tri.v[1]);
                tris.Add(tri.v[2]);
            }
            return(new MeshGeometry3D()
            {
                Positions = pos, TriangleIndices = tris
            });
        }
Exemplo n.º 5
0
        /// <summary>
        /// Finds all edges where the angle between adjacent triangle normal vectors.
        /// is larger than minimumAngle
        /// </summary>
        /// <param name="mesh">
        /// A mesh geometry.
        /// </param>
        /// <param name="minimumAngle">
        /// The minimum angle between the normal vectors of two adjacent triangles (degrees).
        /// </param>
        /// <returns>
        /// The edge indices.
        /// </returns>
        public static Int32Collection FindSharpEdges(this MeshGeometry3D mesh, double minimumAngle)
        {
            var edgeIndices = new Int32Collection();

            // the keys of the dictionary are created from the triangle indices of the edge
            var edgeNormals = new Dictionary <ulong, Vector3D>();

            for (int i = 0; i < mesh.TriangleIndices.Count / 3; i++)
            {
                int i0  = i * 3;
                var p0  = mesh.Positions[mesh.TriangleIndices[i0]];
                var p1  = mesh.Positions[mesh.TriangleIndices[i0 + 1]];
                var p2  = mesh.Positions[mesh.TriangleIndices[i0 + 2]];
                var p10 = p1 - p0;
                var p20 = p2 - p0;
                var n   = SharedFunctions.CrossProduct(ref p10, ref p20);
                n.Normalize();
                for (int j = 0; j < 3; j++)
                {
                    int      index0   = mesh.TriangleIndices[i0 + j];
                    int      index1   = mesh.TriangleIndices[i0 + ((j + 1) % 3)];
                    int      minIndex = Math.Min(index0, index1);
                    int      maxIndex = Math.Max(index0, index1);
                    ulong    key      = CreateKey((uint)minIndex, (uint)maxIndex);
                    Vector3D value;
                    if (edgeNormals.TryGetValue(key, out value))
                    {
                        var n2 = value;
                        n2.Normalize();
                        var angle = 180 / (DoubleOrSingle)Math.PI * (DoubleOrSingle)Math.Acos(SharedFunctions.DotProduct(ref n, ref n2));
                        if (angle > minimumAngle)
                        {
                            edgeIndices.Add(minIndex);
                            edgeIndices.Add(maxIndex);
                        }
                    }
                    else
                    {
                        edgeNormals.Add(key, n);
                    }
                }
            }

            return(edgeIndices);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Finds edges that are only connected to one triangle.
        /// </summary>
        /// <param name="mesh">
        /// A mesh geometry.
        /// </param>
        /// <returns>
        /// The edge indices for the edges that are only used by one triangle.
        /// </returns>
        public static Int32Collection FindBorderEdges(this MeshGeometry3D mesh)
        {
            var dict = new Dictionary <ulong, int>();

            for (int i = 0; i < mesh.TriangleIndices.Count / 3; i++)
            {
                int i0 = i * 3;
                for (int j = 0; j < 3; j++)
                {
                    int   index0   = mesh.TriangleIndices[i0 + j];
                    int   index1   = mesh.TriangleIndices[i0 + ((j + 1) % 3)];
                    int   minIndex = Math.Min(index0, index1);
                    int   maxIndex = Math.Max(index1, index0);
                    ulong key      = CreateKey((uint)minIndex, (uint)maxIndex);
                    if (dict.ContainsKey(key))
                    {
                        dict[key] = dict[key] + 1;
                    }
                    else
                    {
                        dict.Add(key, 1);
                    }
                }
            }

            var edges = new Int32Collection();

            foreach (var kvp in dict)
            {
                // find edges only used by 1 triangle
                if (kvp.Value == 1)
                {
                    uint i0, i1;
                    ReverseKey(kvp.Key, out i0, out i1);
                    edges.Add((int)i0);
                    edges.Add((int)i1);
                }
            }

            return(edges);
        }
Exemplo n.º 7
0
        /// <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));
        }
Exemplo n.º 8
0
 public static System.Windows.Media.Int32Collection ToInt32Collection(SharpDX.Core.IntCollection collection)
 {
     return(new System.Windows.Media.Int32Collection(collection));
 }