/// <overloads>
        /// <summary>
        /// Converts the given <see cref="ITriangleMesh"/> to a <see cref="DcelMesh"/>.
        /// </summary>
        /// </overloads>
        ///
        /// <summary>
        /// Converts the given <see cref="ITriangleMesh"/> to a <see cref="DcelMesh"/>.
        /// </summary>
        /// <param name="mesh">The triangle mesh.</param>
        /// <returns>
        /// The <see cref="DcelMesh"/>.
        /// </returns>
        /// <remarks>
        /// Currently, creating <see cref="DcelMesh"/>es is not supported if the triangle mesh consists
        /// of unconnected sub-meshes or unconnected triangles. All parts of the triangle mesh must be
        /// connected via an edge. (But it is not required that the mesh is closed.)
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="mesh"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="mesh"/> has no vertices or vertex indices.
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// <paramref name="mesh"/> consists of several unconnected components or sub-meshes.
        /// </exception>
        public static DcelMesh FromTriangleMesh(ITriangleMesh mesh)
        {
            if (mesh == null)
            {
                throw new ArgumentNullException("mesh");
            }

            // The simple way: Create a TriangleMesh first.
            var triangleMesh = new TriangleMesh();

            triangleMesh.Add(mesh, false);
            triangleMesh.WeldVertices();

            return(FromTriangleMesh(triangleMesh));
        }
Example #2
0
        private void CreateDualGraph()
        {
            var triangles = new List <CDTriangle>();

            // Convert to TriangleMesh.
            var triangleMesh = _mesh as TriangleMesh;

            if (triangleMesh == null)
            {
                triangleMesh = new TriangleMesh();
                triangleMesh.Add(_mesh, false);
                triangleMesh.WeldVertices();
            }

            // Initialize vertex normals.
            var normals        = new Vector3[triangleMesh.Vertices.Count]; // Vertex normals.
            var neighborCounts = new int[triangleMesh.Vertices.Count];     // Numbers of triangles that touch each vertex.

            for (int i = 0; i < triangleMesh.Vertices.Count; i++)
            {
                normals[i]        = Vector3.Zero;
                neighborCounts[i] = 0;
            }

            // Go through all triangles. Add the normal to normals and increase the neighborCounts
            for (int i = 0; i < triangleMesh.NumberOfTriangles; i++)
            {
                Triangle triangle = triangleMesh.GetTriangle(i);
                var      normal   = triangle.Normal;

                for (int j = 0; j < 3; j++)
                {
                    var vertexIndex = triangleMesh.Indices[(i * 3) + j];
                    normals[vertexIndex]        = normals[vertexIndex] + normal;
                    neighborCounts[vertexIndex] = neighborCounts[vertexIndex] + 1;
                }
            }

            // Create triangles.
            for (int i = 0; i < triangleMesh.NumberOfTriangles; i++)
            {
                Triangle triangle   = triangleMesh.GetTriangle(i);
                var      cdTriangle = new CDTriangle
                {
                    Id       = i,
                    Vertices = new[] { triangle.Vertex0, triangle.Vertex1, triangle.Vertex2 },
                    Normal   = triangle.Normal, // TODO: Special care for degenerate triangles needed?
                };

                for (int j = 0; j < 3; j++)
                {
                    var vertexIndex   = triangleMesh.Indices[(i * 3) + j];
                    var normalSum     = normals[vertexIndex];
                    var neighborCount = neighborCounts[vertexIndex];
                    if (neighborCount > 0)
                    {
                        var normal = normalSum / neighborCount;
                        normal.TryNormalize();
                        cdTriangle.VertexNormals[j] = normal;
                    }
                }

                triangles.Add(cdTriangle);
            }

            // Create an island for each triangle.
            _islands = new List <CDIsland>(triangles.Count);
            for (int i = 0; i < triangles.Count; i++)
            {
                var triangle = triangles[i];

                var island = new CDIsland();
                island.Id        = i;
                island.Triangles = new[] { triangle };
                island.Vertices  = triangle.Vertices;

                island.Aabb = new Aabb(triangle.Vertices[0], triangle.Vertices[0]);
                island.Aabb.Grow(triangle.Vertices[1]);
                island.Aabb.Grow(triangle.Vertices[2]);

                triangle.Island = island;

                _islands.Add(island);
            }

            // Find connectivity (= add neighbor links).
            for (int i = 0; i < triangles.Count; i++)
            {
                var a = triangles[i];
                for (int j = i + 1; j < triangles.Count; j++)
                {
                    var b = triangles[j];
                    CDTriangle.FindNeighbors(a, b);
                }
            }

            // Create links.
            _links = new List <CDIslandLink>();
            for (int i = 0; i < _islands.Count; i++)
            {
                var island   = _islands[i];
                var triangle = island.Triangles[0];

                // Go through all neighbors.
                // If there is a neighbor, create a link.
                // To avoid two links per triangle, we create the link only if the id of this triangle
                // is less than the other island id.
                for (int j = 0; j < 3; j++)
                {
                    CDTriangle neighborTriangle = triangle.Neighbors[j];
                    if (neighborTriangle != null && neighborTriangle.Island.Id > i)
                    {
                        var link = new CDIslandLink(island, neighborTriangle.Island, AllowedConcavity, SmallIslandBoost, IntermediateVertexLimit, SampleTriangleVertices, SampleTriangleCenters);
                        _links.Add(link);
                    }
                }
            }

            // Now, we have a lot of islands with 1 triangle each.
        }