public static Mesh CreateCube(Vector3 scale) { scale *= .5; // the cube is -1 to 1 and I want it to be -.5 to .5 so it is a unit cube. Mesh cube = new Mesh(); Vertex[] verts = new Vertex[8]; verts[0] = cube.CreateVertex(new Vector3(-1, -1, 1) * scale); verts[1] = cube.CreateVertex(new Vector3(1, -1, 1) * scale); verts[2] = cube.CreateVertex(new Vector3(1, 1, 1) * scale); verts[3] = cube.CreateVertex(new Vector3(-1, 1, 1) * scale); verts[4] = cube.CreateVertex(new Vector3(-1, -1, -1) * scale); verts[5] = cube.CreateVertex(new Vector3(1, -1, -1) * scale); verts[6] = cube.CreateVertex(new Vector3(1, 1, -1) * scale); verts[7] = cube.CreateVertex(new Vector3(-1, 1, -1) * scale); // front cube.CreateFace(new Vertex[] { verts[0], verts[1], verts[2], verts[3] }); // left cube.CreateFace(new Vertex[] { verts[4], verts[0], verts[3], verts[7] }); // right cube.CreateFace(new Vertex[] { verts[1], verts[5], verts[6], verts[2] }); // back cube.CreateFace(new Vertex[] { verts[4], verts[7], verts[6], verts[5] }); // top cube.CreateFace(new Vertex[] { verts[3], verts[2], verts[6], verts[7] }); // bottom cube.CreateFace(new Vertex[] { verts[4], verts[5], verts[1], verts[0] }); return cube; }
public override List<Vertex> FindVertices(List<Vertex> vertices, Vector3 position, double maxDistanceToConsiderVertexAsSame) { List<Vertex> foundVertexes = new List<Vertex>(); Vertex testPos = new Vertex(position); int index = vertices.BinarySearch(testPos, this); if (index < 0) { index = ~index; } // we have the starting index now get all the vertices that are close enough starting from here double maxDistanceToConsiderVertexAsSameSquared = maxDistanceToConsiderVertexAsSame * maxDistanceToConsiderVertexAsSame; for (int i = index; i < vertices.Count; i++) { if (Math.Abs(vertices[i].Position.x - position.x) > maxDistanceToConsiderVertexAsSame) { // we are too far away in x, we are done with this direction break; } AddToListIfSameEnough(vertices, position, foundVertexes, maxDistanceToConsiderVertexAsSameSquared, i); } for (int i = index - 1; i >= 0; i--) { if (Math.Abs(vertices[i].Position.x - position.x) > maxDistanceToConsiderVertexAsSame) { // we are too far away in x, we are done with this direction break; } AddToListIfSameEnough(vertices, position, foundVertexes, maxDistanceToConsiderVertexAsSameSquared, i); } return foundVertexes; }
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 static Mesh CreateTetrahedron() { Mesh tetrahedron = new Mesh(); Vector2 basePoint = new Vector2(1, 0); double baseOffsetZ = -Math.Sin(MathHelper.DegreesToRadians(30)); Vertex[] verts = new Vertex[4]; verts[0] = tetrahedron.CreateVertex(new Vector3(basePoint, baseOffsetZ)); verts[1] = tetrahedron.CreateVertex(new Vector3(Vector2.Rotate(basePoint, MathHelper.Tau / 3), baseOffsetZ)); verts[2] = tetrahedron.CreateVertex(new Vector3(Vector2.Rotate(basePoint, 2 * MathHelper.Tau / 3), baseOffsetZ)); verts[3] = tetrahedron.CreateVertex(new Vector3(0, 0, 1)); tetrahedron.CreateFace(new Vertex[] { verts[0], verts[2], verts[1] }); // add reversed because we want to see the bottom. tetrahedron.CreateFace(new Vertex[] { verts[0], verts[1], verts[3] }); tetrahedron.CreateFace(new Vertex[] { verts[1], verts[2], verts[3] }); tetrahedron.CreateFace(new Vertex[] { verts[2], verts[0], verts[3] }); return tetrahedron; }
public static PolygonMesh.Mesh CreateBox(AxisAlignedBoundingBox aabb) { PolygonMesh.Mesh cube = new PolygonMesh.Mesh(); Vertex[] verts = new Vertex[8]; //verts[0] = cube.CreateVertex(new Vector3(-1, -1, 1)); //verts[1] = cube.CreateVertex(new Vector3(1, -1, 1)); //verts[2] = cube.CreateVertex(new Vector3(1, 1, 1)); //verts[3] = cube.CreateVertex(new Vector3(-1, 1, 1)); //verts[4] = cube.CreateVertex(new Vector3(-1, -1, -1)); //verts[5] = cube.CreateVertex(new Vector3(1, -1, -1)); //verts[6] = cube.CreateVertex(new Vector3(1, 1, -1)); //verts[7] = cube.CreateVertex(new Vector3(-1, 1, -1)); verts[0] = cube.CreateVertex(new Vector3(aabb.minXYZ.x, aabb.minXYZ.y, aabb.maxXYZ.z)); verts[1] = cube.CreateVertex(new Vector3(aabb.maxXYZ.x, aabb.minXYZ.y, aabb.maxXYZ.z)); verts[2] = cube.CreateVertex(new Vector3(aabb.maxXYZ.x, aabb.maxXYZ.y, aabb.maxXYZ.z)); verts[3] = cube.CreateVertex(new Vector3(aabb.minXYZ.x, aabb.maxXYZ.y, aabb.maxXYZ.z)); verts[4] = cube.CreateVertex(new Vector3(aabb.minXYZ.x, aabb.minXYZ.y, aabb.minXYZ.z)); verts[5] = cube.CreateVertex(new Vector3(aabb.maxXYZ.x, aabb.minXYZ.y, aabb.minXYZ.z)); verts[6] = cube.CreateVertex(new Vector3(aabb.maxXYZ.x, aabb.maxXYZ.y, aabb.minXYZ.z)); verts[7] = cube.CreateVertex(new Vector3(aabb.minXYZ.x, aabb.maxXYZ.y, aabb.minXYZ.z)); // front cube.CreateFace(new Vertex[] { verts[0], verts[1], verts[2], verts[3] }); // left cube.CreateFace(new Vertex[] { verts[4], verts[0], verts[3], verts[7] }); // right cube.CreateFace(new Vertex[] { verts[1], verts[5], verts[6], verts[2] }); // back cube.CreateFace(new Vertex[] { verts[4], verts[7], verts[6], verts[5] }); // top cube.CreateFace(new Vertex[] { verts[3], verts[2], verts[6], verts[7] }); // bottom cube.CreateFace(new Vertex[] { verts[4], verts[5], verts[1], verts[0] }); return cube; }
public Vertex CreateVertex(Vector3 position, CreateOption createOption = CreateOption.ReuseExisting, SortOption sortOption = SortOption.SortNow) { if (createOption == CreateOption.ReuseExisting) { List<Vertex> existingVertices = FindVertices(position); if (existingVertices != null && existingVertices.Count > 0) { return existingVertices[0]; } } Vertex createdVertex = new Vertex(position); vertices.Add(createdVertex, sortOption); return createdVertex; }
public Vertex this[int index] { get { if (index == 0) { return vertex0; } return vertex1; } set { if (index == 0) { vertex0 = value; } else { vertex1 = value; } } }
internal bool IsConnectedTo(Vertex vertexToCheck) { if (VertexOnEnd[0] == vertexToCheck || VertexOnEnd[1] == vertexToCheck) { return true; } return false; }
public void RemoveFromMeshEdgeLinksOfVertex(Vertex vertexToRemoveFrom) { // lets first fix up the MeshEdge ponted to be 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; } } // no lets clean up the edge links on the meshe edges that are stil connected to the vertexToRemoveFrom MeshEdge nextEdgeThisConnectedTo = GetNextMeshEdgeConnectedTo(vertexToRemoveFrom); if (nextEdgeThisConnectedTo == this) { throw new Exception("You can't disconect 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; // and set this one to null (it has not vertexes) VertexOnEnd[GetVertexEndIndex(vertexToRemoveFrom)] = null; } 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 = nextEdgeThisConnectedTo.GetOpositeVertexEndIndex(vertexToRemoveFrom); edgeConnectedToThis.NextMeshEdgeFromEnd[indexOfThisOnOther] = nextEdgeThisConnectedTo; } }
public int GetVertexEndIndex(Vertex vertexToGetIndexOf) { if (vertexToGetIndexOf == VertexOnEnd[0]) { return 0; } else { if (vertexToGetIndexOf != VertexOnEnd[1]) { // if it is not the first one it must be the other one throw new Exception("You must only ask to get the edge links for a MeshEdge that is linked to the given vertex."); } return 1; } }
public MeshEdge(Vertex vertex1, Vertex vertex2) : this() { this.VertexOnEnd[0] = vertex1; this.VertexOnEnd[1] = vertex2; AddToMeshEdgeLinksOfVertex(vertex1); AddToMeshEdgeLinksOfVertex(vertex2); }
/// <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 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 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 List<MeshEdge> FindMeshEdges(Vertex vertex1, Vertex vertex2) { List<MeshEdge> meshEdges = new List<MeshEdge>(); foreach (MeshEdge meshEdge in vertex1.ConnectedMeshEdges()) { if (meshEdge.IsConnectedTo(vertex2)) { meshEdges.Add(meshEdge); } } return meshEdges; }
public void MergeVertices(Vertex vertexToKeep, Vertex vertexToDelete, bool doActualDeletion = true) { #if false // this check is relatively slow if (!Vertices.ContainsAVertexAtPosition(vertexToKeep) || !Vertices.ContainsAVertexAtPosition(vertexToDelete)) { throw new Exception("Both vertexes have to be part of this mesh to be merged."); } #endif // fix up the mesh edges List<MeshEdge> connectedMeshEdges = vertexToDelete.GetConnectedMeshEdges(); foreach (MeshEdge meshEdgeToFix in connectedMeshEdges) { // fix up the face edges foreach (FaceEdge faceEdge in meshEdgeToFix.FaceEdgesSharingMeshEdge()) { if (faceEdge.firstVertex == vertexToDelete) { faceEdge.firstVertex = vertexToKeep; } } // fix up the mesh edge if (meshEdgeToFix.VertexOnEnd[0] == vertexToDelete) { meshEdgeToFix.VertexOnEnd[0] = vertexToKeep; } else if (meshEdgeToFix.VertexOnEnd[1] == vertexToDelete) { meshEdgeToFix.VertexOnEnd[1] = vertexToKeep; } // make sure it is in the vertex edge loop meshEdgeToFix.AddToMeshEdgeLinksOfVertex(vertexToKeep); } // delete the vertex if (doActualDeletion) { Vertices.Remove(vertexToDelete); } }
public void DeleteVertex(Vertex vertex) { throw new NotImplementedException(); }
public bool ContainsVertex(Vertex vertexToLookFor) { return vertices.ContainsAVertexAtPosition(vertexToLookFor); }
public static Mesh CreateIcosahedron(double scale = 1) { Mesh icosahedron = new Mesh(); double[] icosahedronVertices = { 0, -0.525731, 0.850651, 0.850651, 0, 0.525731, 0.850651, 0, -0.525731, -0.850651, 0, -0.525731, -0.850651, 0, 0.525731, -0.525731, 0.850651, 0, 0.525731, 0.850651, 0, 0.525731, -0.850651, 0, -0.525731, -0.850651, 0, 0, -0.525731, -0.850651, 0, 0.525731, -0.850651, 0, 0.525731, 0.850651 }; int[] icosahedronIndicies = { 1, 2, 6, 1, 7, 2, 3, 4, 5, 4, 3, 8, 6, 5, 11, 5, 6, 10, 9, 10, 2, 10, 9, 3, 7, 8, 9, 8, 7, 0, 11, 0, 1, 0, 11, 4, 6, 2, 10, 1, 6, 11, 3, 5, 10, 5, 4, 11, 2, 7, 9, 7, 1, 0, 3, 9, 8, 4, 8, 0, }; Vertex[] verts = new Vertex[icosahedronVertices.Length / 3]; for (int i = 0; i < icosahedronVertices.Length / 3; i++) { verts[i] = icosahedron.CreateVertex(new Vector3(icosahedronVertices[i * 3 + 0], icosahedronVertices[i * 3 + 1], icosahedronVertices[i * 3 + 2])); } for (int i = 0; i < icosahedronIndicies.Length / 3; i++) { Vertex[] triangleVertices = new Vertex[] { verts[icosahedronIndicies[i * 3 + 0]], verts[icosahedronIndicies[i * 3 + 1]], verts[icosahedronIndicies[i * 3 + 2]], }; icosahedron.CreateFace(triangleVertices); } icosahedron.Transform(Matrix4X4.CreateScale(scale)); return icosahedron; }
public Face CreateFace(Vertex[] verticesToUse, CreateOption createOption = CreateOption.ReuseExisting) { if (verticesToUse.Length == 3 && (verticesToUse[0].Position == verticesToUse[1].Position || verticesToUse[1].Position == verticesToUse[2].Position || verticesToUse[2].Position == verticesToUse[0].Position)) { return null; } if (verticesToUse.Length < 3) { throw new ArgumentException("A face cannot have less than 3 vertices."); } List<MeshEdge> edgesToUse = new List<MeshEdge>(); for (int i = 0; i < verticesToUse.Length - 1; i++) { edgesToUse.Add(CreateMeshEdge(verticesToUse[i], verticesToUse[i + 1], createOption)); } edgesToUse.Add(CreateMeshEdge(verticesToUse[verticesToUse.Length - 1], verticesToUse[0], createOption)); // make the face and set it's data Face createdFace = new Face(); CreateFaceEdges(verticesToUse, edgesToUse, createdFace); createdFace.CalculateNormal(); faces.Add(createdFace); return createdFace; }
public MeshEdge GetNextMeshEdgeConnectedTo(Vertex vertex) { int endVertices = GetVertexEndIndex(vertex); return NextMeshEdgeFromEnd[endVertices]; }
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 int GetOpositeVertexEndIndex(Vertex vertexToNotGetIndexOf) { if (vertexToNotGetIndexOf == VertexOnEnd[0]) { return 1; } else { if (vertexToNotGetIndexOf != VertexOnEnd[1]) { throw new Exception("You must only ask to get the edge links for a MeshEdge that is linked to the given vertex."); } return 0; } }
public override int Compare(Vertex a, Vertex b) { return a.Position.x.CompareTo(b.Position.x); }
public void AddToMeshEdgeLinksOfVertex(Vertex 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 poiting 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; } }
public bool DeleteVertexFromMeshEdge(MeshEdge meshEdgeDeleteVertexFrom, Vertex vertexToDelete) { throw new NotImplementedException(); }
public MeshEdge GetOppositeMeshEdge(Vertex vertexToGetOppositeFor) { if (vertexToGetOppositeFor == VertexOnEnd[0]) { return NextMeshEdgeFromEnd[1]; } else { if (vertexToGetOppositeFor != VertexOnEnd[1]) { throw new Exception("You must only ask to get the opposite vertex on a MeshEdge that is linked to the given vertexToGetOppositeFor."); } return NextMeshEdgeFromEnd[0]; } }
private void DrawVertex(Vertex vertex) { Vector2 imagePosition = GetImagePosition(vertex.Position); DrawCircle(imagePosition, vertexColor); WriteStringAtPos(vertex.Data.ID.ToString(), imagePosition, new RGBA_Bytes()); WriteStringAtPos("{0}".FormatWith(vertex.firstMeshEdge.Data.ID), imagePosition + new Vector2(0, -12), meshEdgeColor); }
public Face FindFace(Vertex[] vertices) { //throw new NotImplementedException(); return null; }
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); }