public static List<Mesh> SplitVolumesIntoMeshes(Mesh meshToSplit, ReportProgressRatio reportProgress) { List<Mesh> discreetVolumes = new List<Mesh>(); HashSet<Face> facesThatHaveBeenAdded = new HashSet<Face>(); Mesh meshFromCurrentVolume = null; Stack<Face> attachedFaces = new Stack<Face>(); for (int faceIndex = 0; faceIndex < meshToSplit.Faces.Count; faceIndex++) { Face currentFace = meshToSplit.Faces[faceIndex]; // If this face as not been added to any volume, create a new volume and add all of the attached faces. if (!facesThatHaveBeenAdded.Contains(currentFace)) { attachedFaces.Push(currentFace); meshFromCurrentVolume = new Mesh(); MeshMaterialData materialDataToCopy = MeshMaterialData.Get(meshToSplit); MeshMaterialData newMaterialData = MeshMaterialData.Get(meshFromCurrentVolume); newMaterialData.MaterialIndex = materialDataToCopy.MaterialIndex; while (attachedFaces.Count > 0) { Face faceToAdd = attachedFaces.Pop(); foreach (Vertex attachedVertex in faceToAdd.Vertices()) { foreach (Face faceAttachedToVertex in attachedVertex.ConnectedFaces()) { if (!facesThatHaveBeenAdded.Contains(faceAttachedToVertex)) { // marke that this face has been taken care of facesThatHaveBeenAdded.Add(faceAttachedToVertex); // add it to the list of faces we need to walk attachedFaces.Push(faceAttachedToVertex); // Add a new face to the new mesh we are creating. List<Vertex> faceVertices = new List<Vertex>(); foreach (FaceEdge faceEdgeToAdd in faceAttachedToVertex.FaceEdges()) { Vertex newVertex = meshFromCurrentVolume.CreateVertex(faceEdgeToAdd.firstVertex.Position, CreateOption.CreateNew, SortOption.WillSortLater); faceVertices.Add(newVertex); } meshFromCurrentVolume.CreateFace(faceVertices.ToArray(), CreateOption.CreateNew); } } } } meshFromCurrentVolume.CleanAndMergMesh(); discreetVolumes.Add(meshFromCurrentVolume); meshFromCurrentVolume = null; } if (reportProgress != null) { double progress = faceIndex / (double)meshToSplit.Faces.Count; bool continueProcessing; reportProgress(progress, "Split Into Meshes", out continueProcessing); } } return discreetVolumes; }
public static Mesh Copy(Mesh meshToCopy, ReportProgressRatio progress = null) { Mesh newMesh = new Mesh(); if (meshToCopy.Vertices.IsSorted) { Dictionary <Vertex, int> vertexIndexDictionary = GetVertexToIndexDictionary(meshToCopy, newMesh); Dictionary <MeshEdge, int> meshEdgeIndexDictionary = GetMeshEdgeToIndexDictionary(meshToCopy, newMesh); for (int faceIndex = 0; faceIndex < meshToCopy.Faces.Count; faceIndex++) { Face faceToCopy = meshToCopy.Faces[faceIndex]; newMesh.Faces.Add(new Face()); } // now set all the data for the new mesh newMesh.Vertices.Capacity = meshToCopy.Vertices.Capacity; for (int vertexIndex = 0; vertexIndex < meshToCopy.Vertices.Count; vertexIndex++) { Vertex vertexToCopy = meshToCopy.Vertices[vertexIndex]; // !!!! ON ERROR !!!!! If this throws an error, you likely need to CleanAndMergMesh the mesh before copying int indexOfFirstMeshEdge = meshEdgeIndexDictionary[vertexToCopy.firstMeshEdge]; Vertex newVertex = newMesh.Vertices[vertexIndex]; newVertex.firstMeshEdge = newMesh.MeshEdges[indexOfFirstMeshEdge]; newVertex.Normal = vertexToCopy.Normal; } newMesh.MeshEdges.Capacity = meshToCopy.MeshEdges.Capacity; for (int meshEdgeIndex = 0; meshEdgeIndex < meshToCopy.MeshEdges.Count; meshEdgeIndex++) { MeshEdge meshEdgeToCopy = meshToCopy.MeshEdges[meshEdgeIndex]; MeshEdge newMeshEdge = newMesh.MeshEdges[meshEdgeIndex]; newMeshEdge.NextMeshEdgeFromEnd[0] = newMesh.MeshEdges[meshEdgeIndexDictionary[meshEdgeToCopy.NextMeshEdgeFromEnd[0]]]; newMeshEdge.NextMeshEdgeFromEnd[1] = newMesh.MeshEdges[meshEdgeIndexDictionary[meshEdgeToCopy.NextMeshEdgeFromEnd[1]]]; newMeshEdge.VertexOnEnd[0] = newMesh.Vertices[vertexIndexDictionary[meshEdgeToCopy.VertexOnEnd[0]]]; newMeshEdge.VertexOnEnd[1] = newMesh.Vertices[vertexIndexDictionary[meshEdgeToCopy.VertexOnEnd[1]]]; // This will get hooked up when we create radial loops with the face edges below //newMeshEdge.firstFaceEdge; //newMesh.MeshEdges.Add(newMeshEdge); } newMesh.Faces.Capacity = meshToCopy.Faces.Capacity; for (int faceIndex = 0; faceIndex < meshToCopy.faces.Count; faceIndex++) { Face faceToCopy = meshToCopy.faces[faceIndex]; Face newface = newMesh.faces[faceIndex]; newface.normal = faceToCopy.normal; // hook up the face edges //public FaceEdge firstFaceEdge; List <Vertex> verticesFromCopy = new List <Vertex>(); List <Vertex> verticesForNew = new List <Vertex>(); foreach (Vertex vertex in faceToCopy.Vertices()) { verticesFromCopy.Add(vertex); verticesForNew.Add(newMesh.Vertices[vertexIndexDictionary[vertex]]); } List <MeshEdge> edgesFromCopy = new List <MeshEdge>(); List <MeshEdge> edgesForNew = new List <MeshEdge>(); for (int i = 0; i < verticesForNew.Count - 1; i++) { MeshEdge meshEdgeFromCopy = verticesFromCopy[i].GetMeshEdgeConnectedToVertex(verticesFromCopy[i + 1]); edgesFromCopy.Add(meshEdgeFromCopy); edgesForNew.Add(newMesh.MeshEdges[meshEdgeIndexDictionary[meshEdgeFromCopy]]); } MeshEdge lastMeshEdgeFromCopy = verticesFromCopy[verticesFromCopy.Count - 1].GetMeshEdgeConnectedToVertex(verticesFromCopy[0]); edgesFromCopy.Add(lastMeshEdgeFromCopy); edgesForNew.Add(newMesh.MeshEdges[meshEdgeIndexDictionary[lastMeshEdgeFromCopy]]); CreateFaceEdges(verticesForNew.ToArray(), edgesForNew, newface); } } else { foreach (Face face in meshToCopy.Faces) { List <Vertex> faceVertices = new List <Vertex>(); foreach (FaceEdge faceEdgeToAdd in face.FaceEdges()) { Vertex newVertex = newMesh.CreateVertex(faceEdgeToAdd.firstVertex.Position, CreateOption.CreateNew, SortOption.WillSortLater); faceVertices.Add(newVertex); } newMesh.CreateFace(faceVertices.ToArray(), CreateOption.CreateNew); } newMesh.CleanAndMergMesh(); } MeshMaterialData materialDataToCopy = MeshMaterialData.Get(meshToCopy); MeshMaterialData newMaterialData = MeshMaterialData.Get(newMesh); newMaterialData.MaterialIndex = materialDataToCopy.MaterialIndex; return(newMesh); }
public static Mesh DoMerge(List<Mesh> meshesToMerge, BackgroundWorker backgroundWorker, int startPercent, int endPercent, bool doCSGMerge = false) { int lengthPercent = endPercent - startPercent; Mesh allPolygons = new Mesh(); if (doCSGMerge) { for (int i = 0; i < meshesToMerge.Count; i++) { Mesh mesh = meshesToMerge[i]; allPolygons = CsgOperations.PerformOperation(allPolygons, mesh, CsgNode.Union); } } else { for (int i = 0; i < meshesToMerge.Count; i++) { Mesh mesh = meshesToMerge[i]; foreach (Face face in mesh.Faces) { List<Vertex> faceVertices = new List<Vertex>(); foreach (FaceEdge faceEdgeToAdd in face.FaceEdges()) { // we allow duplicates (the true) to make sure we are not changing the loaded models acuracy. Vertex newVertex = allPolygons.CreateVertex(faceEdgeToAdd.firstVertex.Position, true, true); faceVertices.Add(newVertex); } // we allow duplicates (the true) to make sure we are not changing the loaded models acuracy. allPolygons.CreateFace(faceVertices.ToArray(), true); } int nextPercent = startPercent + (i + 1) * lengthPercent / meshesToMerge.Count; backgroundWorker.ReportProgress(nextPercent); } allPolygons.CleanAndMergMesh(); } return allPolygons; }
public static Mesh Copy(Mesh meshToCopy, ReportProgressRatio progress = null) { Mesh newMesh = new Mesh(); if (meshToCopy.Vertices.IsSorted) { Dictionary<Vertex, int> vertexIndexDictionary = GetVertexToIndexDictionary(meshToCopy, newMesh); Dictionary<MeshEdge, int> meshEdgeIndexDictionary = GetMeshEdgeToIndexDictionary(meshToCopy, newMesh); for (int faceIndex = 0; faceIndex < meshToCopy.Faces.Count; faceIndex++) { Face faceToCopy = meshToCopy.Faces[faceIndex]; newMesh.Faces.Add(new Face()); } // now set all the data for the new mesh newMesh.Vertices.Capacity = meshToCopy.Vertices.Capacity; for (int vertexIndex = 0; vertexIndex < meshToCopy.Vertices.Count; vertexIndex++) { Vertex vertexToCopy = meshToCopy.Vertices[vertexIndex]; // !!!! ON ERROR !!!!! If this throws an error, you likely need to CleanAndMergMesh the mesh before copying int indexOfFirstMeshEdge = meshEdgeIndexDictionary[vertexToCopy.firstMeshEdge]; Vertex newVertex = newMesh.Vertices[vertexIndex]; newVertex.firstMeshEdge = newMesh.MeshEdges[indexOfFirstMeshEdge]; newVertex.Normal = vertexToCopy.Normal; } newMesh.MeshEdges.Capacity = meshToCopy.MeshEdges.Capacity; for (int meshEdgeIndex = 0; meshEdgeIndex < meshToCopy.MeshEdges.Count; meshEdgeIndex++) { MeshEdge meshEdgeToCopy = meshToCopy.MeshEdges[meshEdgeIndex]; MeshEdge newMeshEdge = newMesh.MeshEdges[meshEdgeIndex]; newMeshEdge.NextMeshEdgeFromEnd[0] = newMesh.MeshEdges[meshEdgeIndexDictionary[meshEdgeToCopy.NextMeshEdgeFromEnd[0]]]; newMeshEdge.NextMeshEdgeFromEnd[1] = newMesh.MeshEdges[meshEdgeIndexDictionary[meshEdgeToCopy.NextMeshEdgeFromEnd[1]]]; newMeshEdge.VertexOnEnd[0] = newMesh.Vertices[vertexIndexDictionary[meshEdgeToCopy.VertexOnEnd[0]]]; newMeshEdge.VertexOnEnd[1] = newMesh.Vertices[vertexIndexDictionary[meshEdgeToCopy.VertexOnEnd[1]]]; // This will get hooked up when we create radial loops with the face edges below //newMeshEdge.firstFaceEdge; //newMesh.MeshEdges.Add(newMeshEdge); } newMesh.Faces.Capacity = meshToCopy.Faces.Capacity; for (int faceIndex = 0; faceIndex < meshToCopy.faces.Count; faceIndex++) { Face faceToCopy = meshToCopy.faces[faceIndex]; Face newface = newMesh.faces[faceIndex]; newface.normal = faceToCopy.normal; // hook up the face edges //public FaceEdge firstFaceEdge; List<Vertex> verticesFromCopy = new List<Vertex>(); List<Vertex> verticesForNew = new List<Vertex>(); foreach (Vertex vertex in faceToCopy.Vertices()) { verticesFromCopy.Add(vertex); verticesForNew.Add(newMesh.Vertices[vertexIndexDictionary[vertex]]); } List<MeshEdge> edgesFromCopy = new List<MeshEdge>(); List<MeshEdge> edgesForNew = new List<MeshEdge>(); for (int i = 0; i < verticesForNew.Count - 1; i++) { MeshEdge meshEdgeFromCopy = verticesFromCopy[i].GetMeshEdgeConnectedToVertex(verticesFromCopy[i + 1]); edgesFromCopy.Add(meshEdgeFromCopy); edgesForNew.Add(newMesh.MeshEdges[meshEdgeIndexDictionary[meshEdgeFromCopy]]); } MeshEdge lastMeshEdgeFromCopy = verticesFromCopy[verticesFromCopy.Count - 1].GetMeshEdgeConnectedToVertex(verticesFromCopy[0]); edgesFromCopy.Add(lastMeshEdgeFromCopy); edgesForNew.Add(newMesh.MeshEdges[meshEdgeIndexDictionary[lastMeshEdgeFromCopy]]); CreateFaceEdges(verticesForNew.ToArray(), edgesForNew, newface); } } else { foreach (Face face in meshToCopy.Faces) { List<Vertex> faceVertices = new List<Vertex>(); foreach (FaceEdge faceEdgeToAdd in face.FaceEdges()) { Vertex newVertex = newMesh.CreateVertex(faceEdgeToAdd.firstVertex.Position, CreateOption.CreateNew, SortOption.WillSortLater); faceVertices.Add(newVertex); } newMesh.CreateFace(faceVertices.ToArray(), CreateOption.CreateNew); } newMesh.CleanAndMergMesh(); } MeshMaterialData materialDataToCopy = MeshMaterialData.Get(meshToCopy); MeshMaterialData newMaterialData = MeshMaterialData.Get(newMesh); newMaterialData.MaterialIndex = materialDataToCopy.MaterialIndex; return newMesh; }