Exemple #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 Core.IntCollection(ti), Normals = n, TextureCoordinates = tc
            });
#else
            return(new MeshGeometry3D {
                Positions = p, TriangleIndices = ti, Normals = n, TextureCoordinates = tc
            });
#endif
        }
Exemple #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);
        }
Exemple #3
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
            });
        }
Exemple #4
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);
        }
Exemple #5
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 Core.IntCollection(ti),
            };
#else
            var result = new MeshGeometry3D {
                Positions = p, TriangleIndices = ti
            };
#endif
            return(result);
        }
Exemple #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);
        }