private static void CreateFaceEdges(Vertex[] verticesToUse, List <MeshEdge> edgesToUse, Face createdFace) { FaceEdge prevFaceEdge = null; for (int i = 0; i < verticesToUse.Length - 1; i++) { MeshEdge currentMeshEdge = edgesToUse[i]; FaceEdge currentFaceEdge = new FaceEdge(createdFace, currentMeshEdge, verticesToUse[i]); if (i == 0) { createdFace.firstFaceEdge = currentFaceEdge; } else { prevFaceEdge.nextFaceEdge = currentFaceEdge; currentFaceEdge.prevFaceEdge = prevFaceEdge; } currentFaceEdge.AddToRadialLoop(currentMeshEdge); prevFaceEdge = currentFaceEdge; } // make the last FaceEdge { MeshEdge currentMeshEdge = edgesToUse[verticesToUse.Length - 1]; FaceEdge currentFaceEdge = new FaceEdge(createdFace, currentMeshEdge, verticesToUse[verticesToUse.Length - 1]); prevFaceEdge.nextFaceEdge = currentFaceEdge; currentFaceEdge.prevFaceEdge = prevFaceEdge; currentFaceEdge.nextFaceEdge = createdFace.firstFaceEdge; createdFace.firstFaceEdge.prevFaceEdge = currentFaceEdge; currentFaceEdge.AddToRadialLoop(currentMeshEdge); } }
public void MergeMeshEdges(MeshEdge edgeToKeep, MeshEdge edgeToDelete, bool doActualDeletion = true) { // make sure they sare vertexes (or they can't be merged) if (!edgeToDelete.IsConnectedTo(edgeToKeep.VertexOnEnd[0]) || !edgeToDelete.IsConnectedTo(edgeToKeep.VertexOnEnd[1])) { throw new Exception("These mesh edges do not share vertexes and can't be merged."); } edgeToDelete.RemoveFromMeshEdgeLinksOfVertex(edgeToKeep.VertexOnEnd[0]); edgeToDelete.RemoveFromMeshEdgeLinksOfVertex(edgeToKeep.VertexOnEnd[1]); // fix any face edges that are referencing the edgeToDelete foreach (FaceEdge attachedFaceEdge in edgeToDelete.firstFaceEdge.RadialNextFaceEdges()) { attachedFaceEdge.meshEdge = edgeToKeep; } List <FaceEdge> radialLoopToMove = new List <FaceEdge>(); foreach (FaceEdge faceEdge in edgeToDelete.firstFaceEdge.RadialNextFaceEdges()) { radialLoopToMove.Add(faceEdge); } foreach (FaceEdge faceEdge in radialLoopToMove) { faceEdge.AddToRadialLoop(edgeToKeep); } if (doActualDeletion) { MeshEdges.Remove(edgeToDelete); } }
public void AddToMeshEdgeLinksOfVertex(IVertex vertexToAddTo) { int endIndex = GetVertexEndIndex(vertexToAddTo); if (vertexToAddTo.FirstMeshEdge == null) { // the vertex is not currently part of any edge // we are the only edge for this vertex so set its links all to this. vertexToAddTo.FirstMeshEdge = this; NextMeshEdgeFromEnd[endIndex] = this; } else // the vertex is already part of an edge (or many) { int endIndexOnFirstMeshEdge = vertexToAddTo.FirstMeshEdge.GetVertexEndIndex(vertexToAddTo); // remember what the one that is there is pointing at MeshEdge vertexCurrentNext = vertexToAddTo.FirstMeshEdge.NextMeshEdgeFromEnd[endIndexOnFirstMeshEdge]; // point the one that is there at us vertexToAddTo.FirstMeshEdge.NextMeshEdgeFromEnd[endIndexOnFirstMeshEdge] = this; // and point the one that are already there at this. this.NextMeshEdgeFromEnd[endIndex] = vertexCurrentNext; } }
private void DrawMeshEdge(MeshEdge meshEdge) { Vector2 start = GetImagePosition(meshEdge.VertexOnEnd[0].Position); Vector2 end = GetImagePosition(meshEdge.VertexOnEnd[1].Position); DrawEdgeLine(start, end, "{0}".FormatWith(meshEdge.ID), meshEdgeColor); if (meshEdge.firstFaceEdge != null) { WriteStringAtPos("{0}".FormatWith(meshEdge.firstFaceEdge.ID), (start + end) / 2 + new Vector2(0, 12), faceEdgeColor); } else { WriteStringAtPos("null", (start + end) / 2 + new Vector2(0, 12), faceEdgeColor); } Vector2 delta = end - start; Vector2 normal = delta.GetNormal(); double length = delta.Length; Vector2 left = normal.GetPerpendicularLeft(); WriteStringAtPos("{0}".FormatWith(meshEdge.NextMeshEdgeFromEnd[0].ID), start + normal * length * .40, meshEdgeColor); WriteStringAtPos("{0}".FormatWith(meshEdge.VertexOnEnd[0].ID), start + normal * length * .10, vertexColor); WriteStringAtPos("{0}".FormatWith(meshEdge.NextMeshEdgeFromEnd[1].ID), start + normal * length * .60, meshEdgeColor); WriteStringAtPos("{0}".FormatWith(meshEdge.VertexOnEnd[1].ID), start + normal * length * .90, vertexColor); }
public MeshEdge CreateMeshEdge(Vertex vertex1, Vertex vertex2, CreateOption createOption = CreateOption.ReuseExisting) { if (false) //!vertices.Contains(vertex1) || !vertices.Contains(vertex2)) { throw new ArgumentException("the two vertices must be in the vertices list before a mesh edge can be made between them."); } if (vertex1 == vertex2) { throw new ArgumentException("Your input vertices must not be the same vertex."); } if (createOption == CreateOption.ReuseExisting) { MeshEdge existingMeshEdge = vertex1.GetMeshEdgeConnectedToVertex(vertex2); if (existingMeshEdge != null) { return(existingMeshEdge); } } MeshEdge createdMeshEdge = new MeshEdge(vertex1, vertex2); MeshEdges.Add(createdMeshEdge); return(createdMeshEdge); }
public void UnsplitFace(Face faceToKeep, Face faceToDelete, MeshEdge meshEdgeToDelete) { if (faceToKeep == faceToDelete) { throw new Exception("Can't join face to itself"); } // validate the edgeToDelete is in both faces, edgeToDelete is only in these two faces, the two faces only share this one edge and no other edges FaceEdge faceEdgeToDeleteOnFaceToKeep = meshEdgeToDelete.GetFaceEdge(faceToKeep); FaceEdge faceEdgeToDeleteOnFaceToDelete = meshEdgeToDelete.GetFaceEdge(faceToDelete); if (faceEdgeToDeleteOnFaceToKeep.firstVertex == faceEdgeToDeleteOnFaceToDelete.firstVertex) { throw new Exception("The faces have oposite windings and you cannot merge the edge"); } faceEdgeToDeleteOnFaceToKeep.prevFaceEdge.nextFaceEdge = faceEdgeToDeleteOnFaceToDelete.nextFaceEdge; faceEdgeToDeleteOnFaceToDelete.nextFaceEdge.prevFaceEdge = faceEdgeToDeleteOnFaceToKeep.prevFaceEdge; faceEdgeToDeleteOnFaceToKeep.nextFaceEdge.prevFaceEdge = faceEdgeToDeleteOnFaceToDelete.prevFaceEdge; faceEdgeToDeleteOnFaceToDelete.prevFaceEdge.nextFaceEdge = faceEdgeToDeleteOnFaceToKeep.nextFaceEdge; // if the face we are deleting is the one that the face to keep was looking at as its starting face edge, move it to the next face edge if (faceToKeep.firstFaceEdge == faceEdgeToDeleteOnFaceToKeep) { faceToKeep.firstFaceEdge = faceToKeep.firstFaceEdge.nextFaceEdge; } // make sure the FaceEdges all point to the kept face. foreach (FaceEdge faceEdge in faceToKeep.firstFaceEdge.NextFaceEdges()) { faceEdge.containingFace = faceToKeep; } // make sure we take the mesh edge out of the neighbors pointers meshEdgeToDelete.RemoveFromMeshEdgeLinksOfVertex(meshEdgeToDelete.VertexOnEnd[0]); meshEdgeToDelete.RemoveFromMeshEdgeLinksOfVertex(meshEdgeToDelete.VertexOnEnd[1]); // clear the data on the deleted face edge to help with debugging faceEdgeToDeleteOnFaceToKeep.meshEdge.VertexOnEnd[0] = null; faceEdgeToDeleteOnFaceToKeep.meshEdge.VertexOnEnd[1] = null; faceToDelete.firstFaceEdge = null; // take the face out of the face list faces.Remove(faceToDelete); // clear the data on the deleted mesh edge to help with debugging meshEdgeToDelete.firstFaceEdge = null; meshEdgeToDelete.VertexOnEnd[0] = null; meshEdgeToDelete.NextMeshEdgeFromEnd[0] = null; meshEdgeToDelete.VertexOnEnd[1] = null; meshEdgeToDelete.NextMeshEdgeFromEnd[1] = null; MeshEdges.Remove(meshEdgeToDelete); }
public FaceEdge(Face face, MeshEdge meshEdge, Vertex vertex) { this.containingFace = face; this.meshEdge = meshEdge; this.firstVertex = vertex; nextFaceEdge = null; prevFaceEdge = null; radialNextFaceEdge = radialPrevFaceEdge = this; }
public FaceEdge(Face face, MeshEdge meshEdge, IVertex vertex) { this.ContainingFace = face; this.MeshEdge = meshEdge; this.FirstVertex = vertex; NextFaceEdge = null; PrevFaceEdge = null; RadialNextFaceEdge = radialPrevFaceEdge = this; }
private static Dictionary <MeshEdge, int> GetMeshEdgeToIndexDictionary(Mesh meshToCopy, Mesh newMesh) { Dictionary <MeshEdge, int> meshEdgeIndexDictionary = new Dictionary <MeshEdge, int>(meshToCopy.MeshEdges.Count); for (int edgeIndex = 0; edgeIndex < meshToCopy.MeshEdges.Count; edgeIndex++) { MeshEdge edgeToCopy = meshToCopy.MeshEdges[edgeIndex]; meshEdgeIndexDictionary.Add(edgeToCopy, edgeIndex); newMesh.MeshEdges.Add(new MeshEdge()); } return(meshEdgeIndexDictionary); }
public void SplitMeshEdge(MeshEdge meshEdgeToSplit, out Vertex vertexCreatedDuringSplit, out MeshEdge meshEdgeCreatedDuringSplit) { // create our new Vertex and MeshEdge { // make a new vertex between the existing ones // TODO: make this create an interpolated vertex, check if it exits and add it or use the right one. //vertexCreatedDuringSplit = meshEdgeToSplit.edgeEndVertex[0].CreateInterpolated(meshEdgeToSplit.edgeEndVertex[1], .5); vertexCreatedDuringSplit = CreateVertex((meshEdgeToSplit.VertexOnEnd[0].Position + meshEdgeToSplit.VertexOnEnd[1].Position) / 2); // TODO: check if the mesh edge exits and use the existing one (or not) meshEdgeCreatedDuringSplit = new MeshEdge(); } // Set the new firstMeshEdge on the new Vertex vertexCreatedDuringSplit.firstMeshEdge = meshEdgeCreatedDuringSplit; Vertex existingVertexToConectTo = meshEdgeToSplit.VertexOnEnd[1]; // fix the Vertex references on the MeshEdges { // and set the edges to point to this new one meshEdgeCreatedDuringSplit.VertexOnEnd[0] = vertexCreatedDuringSplit; meshEdgeCreatedDuringSplit.VertexOnEnd[1] = existingVertexToConectTo; meshEdgeToSplit.VertexOnEnd[1] = vertexCreatedDuringSplit; } // fix the MeshEdgeLinks on the MeshEdges { // set the created edge to be connected to the old edges other mesh edges meshEdgeCreatedDuringSplit.NextMeshEdgeFromEnd[0] = meshEdgeToSplit; // make anything that pointed to the split edge point to the new mesh edge meshEdgeToSplit.NextMeshEdgeFromEnd[1] = meshEdgeCreatedDuringSplit; } // if the MeshEdge is part of a face than we have to fix the face up FaceEdge faceEdgeToSplit = meshEdgeToSplit.firstFaceEdge; if (faceEdgeToSplit != null) { foreach (FaceEdge faceEdge in meshEdgeToSplit.FaceEdgesSharingMeshEdge()) { Face currentFace = faceEdge.containingFace; FaceEdge newFaceEdge = new FaceEdge(currentFace, meshEdgeCreatedDuringSplit, vertexCreatedDuringSplit); newFaceEdge.AddToRadialLoop(meshEdgeCreatedDuringSplit); // and inject it into the face loop for this face newFaceEdge.prevFaceEdge = faceEdge; newFaceEdge.nextFaceEdge = faceEdge.nextFaceEdge; faceEdge.nextFaceEdge.prevFaceEdge = newFaceEdge; faceEdge.nextFaceEdge = newFaceEdge; } } }
public IEnumerable <MeshEdge> ConnectedMeshEdges() { if (this.firstMeshEdge != null) { MeshEdge curMeshEdge = this.firstMeshEdge; do { yield return(curMeshEdge); curMeshEdge = curMeshEdge.GetNextMeshEdgeConnectedTo(this); } while (curMeshEdge != this.firstMeshEdge); } }
public void RemoveFromMeshEdgeLinksOfVertex(IVertex vertexToRemoveFrom) { // lets first fix up the MeshEdge pointed to by the vertexToRemoveFrom if (vertexToRemoveFrom.FirstMeshEdge == this) { MeshEdge nextMeshEdgeConnectedToThisVertex = vertexToRemoveFrom.FirstMeshEdge.GetNextMeshEdgeConnectedTo(vertexToRemoveFrom); // if this is a radial loop if (nextMeshEdgeConnectedToThisVertex == vertexToRemoveFrom.FirstMeshEdge) { // the vertex is connected to no edges vertexToRemoveFrom.FirstMeshEdge = null; return; } else { // hook it up to the next connected mesh edge vertexToRemoveFrom.FirstMeshEdge = nextMeshEdgeConnectedToThisVertex; } } // now lets clean up the edge links on the mesh edges that are still connected to the vertexToRemoveFrom MeshEdge nextEdgeThisConnectedTo = GetNextMeshEdgeConnectedTo(vertexToRemoveFrom); if (nextEdgeThisConnectedTo == this) { throw new Exception("You can't disconnect when you are the only mesh edge."); } MeshEdge edgeAfterEdgeWeAreConnectedTo = nextEdgeThisConnectedTo.GetNextMeshEdgeConnectedTo(vertexToRemoveFrom); if (edgeAfterEdgeWeAreConnectedTo == this) { // if only 2 edges (this and other) then set the other one to a circular reference to itself int indexOnEdgeWeAreConnectedTo = nextEdgeThisConnectedTo.GetVertexEndIndex(vertexToRemoveFrom); nextEdgeThisConnectedTo.NextMeshEdgeFromEnd[indexOnEdgeWeAreConnectedTo] = nextEdgeThisConnectedTo; } else { // we need to find the edge that has a reference to this one MeshEdge edgeConnectedToThis = edgeAfterEdgeWeAreConnectedTo; while (edgeConnectedToThis.GetNextMeshEdgeConnectedTo(vertexToRemoveFrom) != this) { edgeConnectedToThis = edgeConnectedToThis.GetNextMeshEdgeConnectedTo(vertexToRemoveFrom); } int indexOfThisOnOther = edgeConnectedToThis.GetVertexEndIndex(vertexToRemoveFrom); edgeConnectedToThis.NextMeshEdgeFromEnd[indexOfThisOnOther] = nextEdgeThisConnectedTo; } // and set this one to null (it has no vertices) VertexOnEnd[GetVertexEndIndex(vertexToRemoveFrom)] = null; }
public void MergeMeshEdges(ReportProgressRatio reportProgress = null) { HashSet <MeshEdge> markedForDeletion = new HashSet <MeshEdge>(); Stopwatch maxProgressReport = new Stopwatch(); maxProgressReport.Start(); for (int i = 0; i < MeshEdges.Count; i++) { MeshEdge currentMeshEdge = MeshEdges[i]; if (!markedForDeletion.Contains(currentMeshEdge)) { Vertex vertex0 = currentMeshEdge.VertexOnEnd[0]; Vertex vertex1 = currentMeshEdge.VertexOnEnd[1]; // find out if there is another edge attached to the same vertexes List <MeshEdge> meshEdgesToDelete = FindMeshEdges(vertex0, vertex1); if (meshEdgesToDelete.Count > 1) { foreach (MeshEdge meshEdgeToDelete in meshEdgesToDelete) { if (meshEdgeToDelete != currentMeshEdge) { if (!markedForDeletion.Contains(meshEdgeToDelete)) { MergeMeshEdges(currentMeshEdge, meshEdgeToDelete, false); markedForDeletion.Add(meshEdgeToDelete); } } } } } if (reportProgress != null) { if (maxProgressReport.ElapsedMilliseconds > 200) { bool continueProcessing; reportProgress(i / (double)MeshEdges.Count, "Merging Mesh Edges", out continueProcessing); maxProgressReport.Restart(); if (!continueProcessing) { return; } } } } RemoveMeshEdgesMarkedForDeletion(markedForDeletion); }
private void RemoveMeshEdgesMarkedForDeletion(HashSet <MeshEdge> markedForDeletion) { List <MeshEdge> NonDeleteMeshEdges = new List <MeshEdge>(); for (int i = 0; i < MeshEdges.Count; i++) { MeshEdge meshEdgeToCheck = MeshEdges[i]; if (!markedForDeletion.Contains(meshEdgeToCheck)) { NonDeleteMeshEdges.Add(meshEdgeToCheck); } } meshEdges = NonDeleteMeshEdges; }
public void AddToRadialLoop(MeshEdge currentMeshEdge) { if (currentMeshEdge.firstFaceEdge == null) { // This is the first face edge of this mesh edge. Add it. currentMeshEdge.firstFaceEdge = this; } else { // There was a face on this mesh edge so add this one in. // First set the new face edge radius pointers this.radialPrevFaceEdge = currentMeshEdge.firstFaceEdge; this.RadialNextFaceEdge = currentMeshEdge.firstFaceEdge.RadialNextFaceEdge; // then fix the insertion point to point to this new face edge. this.radialPrevFaceEdge.RadialNextFaceEdge = this; this.RadialNextFaceEdge.radialPrevFaceEdge = this; } }
public MeshEdge this[int index] { get { if (index == 0) { return nextMeshEdge0; } return nextMeshEdge1; } set { if (index == 0) { nextMeshEdge0 = value; } else { nextMeshEdge1 = value; } } }
public MeshEdge this[int index] { get { if (index == 0) { return(nextMeshEdge0); } return(nextMeshEdge1); } set { if (index == 0) { nextMeshEdge0 = value; } else { nextMeshEdge1 = value; } } }
public void MergeMeshEdges(MeshEdge edgeToKeep, MeshEdge edgeToDelete, bool doActualDeletion = true) { // make sure they share vertexes (or they can't be merged) if (!edgeToDelete.IsConnectedTo(edgeToKeep.VertexOnEnd[0]) || !edgeToDelete.IsConnectedTo(edgeToKeep.VertexOnEnd[1])) { throw new Exception("These mesh edges do not share vertexes and can't be merged."); } edgeToDelete.RemoveFromMeshEdgeLinksOfVertex(edgeToKeep.VertexOnEnd[0]); edgeToDelete.RemoveFromMeshEdgeLinksOfVertex(edgeToKeep.VertexOnEnd[1]); // fix any face edges that are referencing the edgeToDelete foreach (FaceEdge attachedFaceEdge in edgeToDelete.firstFaceEdge.RadialNextFaceEdges()) { attachedFaceEdge.meshEdge = edgeToKeep; } List<FaceEdge> radialLoopToMove = new List<FaceEdge>(); foreach (FaceEdge faceEdge in edgeToDelete.firstFaceEdge.RadialNextFaceEdges()) { radialLoopToMove.Add(faceEdge); } foreach (FaceEdge faceEdge in radialLoopToMove) { faceEdge.AddToRadialLoop(edgeToKeep); } if (doActualDeletion) { MeshEdges.Remove(edgeToDelete); } }
public void DeleteMeshEdge(MeshEdge meshEdgeToDelete) { // make sure we take the mesh edge out of the neighbors pointers meshEdgeToDelete.RemoveFromMeshEdgeLinksOfVertex(meshEdgeToDelete.VertexOnEnd[0]); meshEdgeToDelete.RemoveFromMeshEdgeLinksOfVertex(meshEdgeToDelete.VertexOnEnd[1]); // clear the data on the deleted mesh edge to help with debugging meshEdgeToDelete.firstFaceEdge = null; meshEdgeToDelete.VertexOnEnd[0] = null; meshEdgeToDelete.NextMeshEdgeFromEnd[0] = null; meshEdgeToDelete.VertexOnEnd[1] = null; meshEdgeToDelete.NextMeshEdgeFromEnd[1] = null; MeshEdges.Remove(meshEdgeToDelete); }
public void SplitFace(Face faceToSplit, Vertex splitStartVertex, Vertex splitEndVertex, out MeshEdge meshEdgeCreatedDuringSplit, out Face faceCreatedDuringSplit) { if (!ContainsVertex(splitStartVertex) || !ContainsVertex(splitEndVertex)) { throw new Exception("The mesh must contain the vertices you intend to split between."); } // we may want to be able to double up an edge for some operations (we'll have to see). if (FindMeshEdges(splitStartVertex, splitEndVertex).Count > 0) { // this also ensures that the face is more than 2 sided. throw new Exception("You cannot split a face on an existing edge."); } FaceEdge faceEdgeAfterSplitStart = null; FaceEdge faceEdgeAfterSplitEnd = null; int count = 0; foreach (FaceEdge faceEdge in faceToSplit.FaceEdges()) { if (faceEdge.firstVertex == splitStartVertex) { faceEdgeAfterSplitStart = faceEdge; count++; } else if (faceEdge.firstVertex == splitEndVertex) { faceEdgeAfterSplitEnd = faceEdge; count++; } if (count == 2) { break; // stop if we found both face edges } } meshEdgeCreatedDuringSplit = CreateMeshEdge(splitStartVertex, splitEndVertex); faceCreatedDuringSplit = new Face(faceToSplit); faces.Add(faceCreatedDuringSplit); FaceEdge newFaceEdgeExistingFace = new FaceEdge(faceToSplit, meshEdgeCreatedDuringSplit, splitStartVertex); FaceEdge newFaceEdgeForNewFace = new FaceEdge(faceCreatedDuringSplit, meshEdgeCreatedDuringSplit, splitEndVertex); // get the new edges injected into the existing loop, spliting it in two. newFaceEdgeExistingFace.prevFaceEdge = faceEdgeAfterSplitStart.prevFaceEdge; newFaceEdgeForNewFace.prevFaceEdge = faceEdgeAfterSplitEnd.prevFaceEdge; faceEdgeAfterSplitStart.prevFaceEdge.nextFaceEdge = newFaceEdgeExistingFace; faceEdgeAfterSplitEnd.prevFaceEdge.nextFaceEdge = newFaceEdgeForNewFace; newFaceEdgeExistingFace.nextFaceEdge = faceEdgeAfterSplitEnd; newFaceEdgeForNewFace.nextFaceEdge = faceEdgeAfterSplitStart; faceEdgeAfterSplitStart.prevFaceEdge = newFaceEdgeForNewFace; faceEdgeAfterSplitEnd.prevFaceEdge = newFaceEdgeExistingFace; // make sure the first face edge of each face is valid faceToSplit.firstFaceEdge = newFaceEdgeExistingFace; faceCreatedDuringSplit.firstFaceEdge = newFaceEdgeForNewFace; // make sure the FaceEdges of the new face all point to the new face. foreach (FaceEdge faceEdge in faceCreatedDuringSplit.firstFaceEdge.NextFaceEdges()) { faceEdge.containingFace = faceCreatedDuringSplit; } newFaceEdgeExistingFace.AddToRadialLoop(meshEdgeCreatedDuringSplit); newFaceEdgeForNewFace.AddToRadialLoop(meshEdgeCreatedDuringSplit); }
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); }
private void DrawMeshEdge(MeshEdge meshEdge) { Vector2 start = GetImagePosition(meshEdge.VertexOnEnd[0].Position); Vector2 end = GetImagePosition(meshEdge.VertexOnEnd[1].Position); DrawEdgeLine(start, end, "{0}".FormatWith(meshEdge.Data.ID), meshEdgeColor); if (meshEdge.firstFaceEdge != null) { WriteStringAtPos("{0}".FormatWith(meshEdge.firstFaceEdge.Data.ID), (start + end) / 2 + new Vector2(0, 12), faceEdgeColor); } else { WriteStringAtPos("null", (start + end) / 2 + new Vector2(0, 12), faceEdgeColor); } Vector2 delta = end - start; Vector2 normal = delta.GetNormal(); double length = delta.Length; Vector2 left = normal.GetPerpendicularLeft(); WriteStringAtPos("{0}".FormatWith(meshEdge.NextMeshEdgeFromEnd[0].Data.ID), start + normal * length * .40, meshEdgeColor); WriteStringAtPos("{0}".FormatWith(meshEdge.VertexOnEnd[0].Data.ID), start + normal * length * .10, vertexColor); WriteStringAtPos("{0}".FormatWith(meshEdge.NextMeshEdgeFromEnd[1].Data.ID), start + normal * length * .60, meshEdgeColor); WriteStringAtPos("{0}".FormatWith(meshEdge.VertexOnEnd[1].Data.ID), start + normal * length * .90, vertexColor); }
public void DeleteMeshEdge(MeshEdge meshEdgeToDelete) { }
public bool DeleteMeshEdgeFromFace(Face faceToDeleteEdgeFrom, MeshEdge meshEdgeToDelete) { throw new NotImplementedException(); }
public void UnsplitFace(Face faceToKeep, Face faceToDelete, MeshEdge meshEdgeToDelete) { if (faceToKeep == faceToDelete) { throw new Exception("Can't join face to itself"); } // validate the edgeToDelete is in both faces, edgeToDelete is only in these two faces, the two faces only share this one edge and no other edges FaceEdge faceEdgeToDeleteOnFaceToKeep = meshEdgeToDelete.GetFaceEdge(faceToKeep); FaceEdge faceEdgeToDeleteOnFaceToDelete = meshEdgeToDelete.GetFaceEdge(faceToDelete); if (faceEdgeToDeleteOnFaceToKeep.firstVertex == faceEdgeToDeleteOnFaceToDelete.firstVertex) { throw new Exception("The faces have oposite windings and you cannot merge the edge"); } faceEdgeToDeleteOnFaceToKeep.prevFaceEdge.nextFaceEdge = faceEdgeToDeleteOnFaceToDelete.nextFaceEdge; faceEdgeToDeleteOnFaceToDelete.nextFaceEdge.prevFaceEdge = faceEdgeToDeleteOnFaceToKeep.prevFaceEdge; faceEdgeToDeleteOnFaceToKeep.nextFaceEdge.prevFaceEdge = faceEdgeToDeleteOnFaceToDelete.prevFaceEdge; faceEdgeToDeleteOnFaceToDelete.prevFaceEdge.nextFaceEdge = faceEdgeToDeleteOnFaceToKeep.nextFaceEdge; // if the face we are deleting is the one that the face to keep was looking at as its starting face edge, move it to the next face edge if (faceToKeep.firstFaceEdge == faceEdgeToDeleteOnFaceToKeep) { faceToKeep.firstFaceEdge = faceToKeep.firstFaceEdge.nextFaceEdge; } // make sure the FaceEdges all point to the kept face. foreach (FaceEdge faceEdge in faceToKeep.firstFaceEdge.NextFaceEdges()) { faceEdge.containingFace = faceToKeep; } DeleteMeshEdge(meshEdgeToDelete); // clear the data on the deleted face edge to help with debugging faceEdgeToDeleteOnFaceToKeep.meshEdge.VertexOnEnd[0] = null; faceEdgeToDeleteOnFaceToKeep.meshEdge.VertexOnEnd[1] = null; faceToDelete.firstFaceEdge = null; // take the face out of the face list faces.Remove(faceToDelete); }
public bool DeleteVertexFromMeshEdge(MeshEdge meshEdgeDeleteVertexFrom, Vertex vertexToDelete) { throw new NotImplementedException(); }
public void AddToRadialLoop(MeshEdge currentMeshEdge) { if (currentMeshEdge.firstFaceEdge == null) { // This is the first face edge of this mesh edge. Add it. currentMeshEdge.firstFaceEdge = this; } else { // There was a face on this mesh edge so add this one in. // First set the new face edge radias pointers this.radialPrevFaceEdge = currentMeshEdge.firstFaceEdge; this.radialNextFaceEdge = currentMeshEdge.firstFaceEdge.radialNextFaceEdge; // then fix the insertion point to point to this new face edge. this.radialPrevFaceEdge.radialNextFaceEdge = this; this.radialNextFaceEdge.radialPrevFaceEdge = this; } }
/// <summary> /// Unsplit (merge) the edgeToJoin and the edge that it is connected to through vertexToDelete. /// Only unsplit the edge if we are reversing what would have been a split (a single vertex connecting only two edges). /// </summary> /// <param name="edgeToJoin"></param> /// <param name="vertexToDelete"></param> /// <returns></returns> public void UnsplitMeshEdge(MeshEdge edgeToJoin, Vertex vertexToDelete) { int endToJoinIndex = edgeToJoin.GetVertexEndIndex(vertexToDelete); MeshEdge edgeToDelete = edgeToJoin.GetNextMeshEdgeConnectedTo(vertexToDelete); if (edgeToDelete.GetNextMeshEdgeConnectedTo(vertexToDelete) != edgeToJoin) { // make sure the edgeToJoin is a valid unsplit (only one connection) throw new Exception("The edge that is being unsplit must be connected to only one other MeshEdge across the vertexToDelete."); } int otherEndOfEdgeToDelete = edgeToDelete.GetOpositeVertexEndIndex(vertexToDelete); MeshEdge edgeToJoinTo = edgeToDelete.NextMeshEdgeFromEnd[otherEndOfEdgeToDelete]; // if the MeshEdge is part of any faces than we have to fix the faces. if (edgeToJoin.firstFaceEdge != null) { // The edge we split was part of one or more faces, we need to fix the FaceEdge loops foreach (FaceEdge faceEdge in edgeToJoin.FaceEdgesSharingMeshEdge()) { FaceEdge faceEdgeToDelete = null; if (faceEdge.nextFaceEdge.meshEdge == edgeToDelete) { faceEdgeToDelete = faceEdge.nextFaceEdge; FaceEdge newNextFaceEdge = faceEdgeToDelete.nextFaceEdge; newNextFaceEdge.prevFaceEdge = faceEdge; faceEdge.nextFaceEdge = newNextFaceEdge; } else if (faceEdge.prevFaceEdge.meshEdge == edgeToDelete) { faceEdgeToDelete = faceEdge.prevFaceEdge; FaceEdge newPrevFaceEdge = faceEdgeToDelete.prevFaceEdge; newPrevFaceEdge.nextFaceEdge = faceEdge; faceEdge.prevFaceEdge = newPrevFaceEdge; } else { throw new Exception("Either the next or prev edge must be the same as the edge to delete."); } // if the FaceEdge we are deleting is the one that the face was using as its firstFaceEdge, change it. if (faceEdge.containingFace.firstFaceEdge == faceEdgeToDelete) { faceEdge.containingFace.firstFaceEdge = faceEdge; } // and clear out the FaceEdge we are deleting to help debugging and other references to it. faceEdgeToDelete.nextFaceEdge = null; faceEdgeToDelete.prevFaceEdge = null; faceEdgeToDelete.radialNextFaceEdge = null; faceEdgeToDelete.radialPrevFaceEdge = null; faceEdgeToDelete.meshEdge = null; faceEdgeToDelete.containingFace = null; faceEdgeToDelete.firstVertex = null; } } // fix the MeshEdgeLinks on the edgeToJoin { edgeToJoin.VertexOnEnd[endToJoinIndex] = edgeToDelete.VertexOnEnd[otherEndOfEdgeToDelete]; edgeToJoin.NextMeshEdgeFromEnd[endToJoinIndex] = edgeToDelete.NextMeshEdgeFromEnd[otherEndOfEdgeToDelete]; } // Clear all the data on the deleted vertex and edge so we have less code that will work if it continues to use them. vertexToDelete.firstMeshEdge = null; edgeToDelete.firstFaceEdge = null; edgeToDelete.VertexOnEnd[0] = null; edgeToDelete.NextMeshEdgeFromEnd[0] = null; edgeToDelete.VertexOnEnd[1] = null; edgeToDelete.NextMeshEdgeFromEnd[1] = null; }
public MeshEdge CreateMeshEdge(Vertex vertex1, Vertex vertex2, CreateOption createOption = CreateOption.ReuseExisting) { if (false)//!vertices.Contains(vertex1) || !vertices.Contains(vertex2)) { throw new ArgumentException("the two vertices must be in the vertices list before a mesh edge can be made between them."); } if (vertex1 == vertex2) { throw new ArgumentException("Your input vertices must not be the same vertex."); } if (createOption == CreateOption.ReuseExisting) { MeshEdge existingMeshEdge = vertex1.GetMeshEdgeConnectedToVertex(vertex2); if (existingMeshEdge != null) { return existingMeshEdge; } } MeshEdge createdMeshEdge = new MeshEdge(vertex1, vertex2); MeshEdges.Add(createdMeshEdge); return createdMeshEdge; }
public static IReadOnlyList <MeshEdge> NewMeshEdges(this Mesh mesh) { return(MeshEdge.CreateMeshEdgeList(mesh, VertexFaceList.CreateVertexFaceList(mesh))); }