/// <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)); }
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. }