private void DrawFaceEdge(FaceEdge faceEdge, Vector2 faceAverageCenter)
        {
            Vector2 start = MoveTowardsCenter(GetImagePosition(faceEdge.FirstVertex.Position), faceAverageCenter);
            Vector2 end   = MoveTowardsCenter(GetImagePosition(faceEdge.NextFaceEdge.FirstVertex.Position), faceAverageCenter);

            DrawEdgeLine(start, end, faceEdge.ID.ToString(), faceEdgeColor);
            graphics.Circle(start, 3, Color.Black);
            WriteStringAtPos("{0}".FormatWith(faceEdge.MeshEdge.ID), (start + end) / 2 + new Vector2(0, -12), meshEdgeColor);
            WriteStringAtPos("{0}".FormatWith(faceEdge.ContainingFace.ID), (start + end) / 2 + new Vector2(0, 12), faceColor);

            Vector2 delta  = end - start;
            Vector2 normal = delta.GetNormal();
            double  length = delta.Length;
            Vector2 left   = normal.GetPerpendicularLeft();

            // draw the starting vertex info
            WriteStringAtPos("{0}".FormatWith(faceEdge.FirstVertex.ID), start + normal * length * .10, vertexColor);

            // draw the next and prev faceEdge info
            WriteStringAtPos("{0}".FormatWith(faceEdge.NextFaceEdge.ID), start + normal * length * .60, faceEdgeColor);
            WriteStringAtPos("{0}".FormatWith(faceEdge.PrevFaceEdge.ID), start + normal * length * .40, faceEdgeColor);

            // draw the radialFaceEdge info
            WriteStringAtPos("{0}".FormatWith(faceEdge.RadialNextFaceEdge.ID), start + new Vector2(0, 7) + normal * length * .90, faceEdgeColor);
            WriteStringAtPos("{0}".FormatWith(faceEdge.radialPrevFaceEdge.ID), start + new Vector2(0, -7) + normal * length * .90, faceEdgeColor);
        }
示例#2
0
        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);
            }
        }
示例#3
0
        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);
        }
示例#4
0
        public FaceEdge(Face face, MeshEdge meshEdge, Vertex vertex)
        {
            this.containingFace = face;
            this.meshEdge       = meshEdge;
            this.firstVertex    = vertex;

            nextFaceEdge = null;
            prevFaceEdge = null;

            radialNextFaceEdge = radialPrevFaceEdge = this;
        }
示例#5
0
        public IEnumerable <FaceEdge> NextFaceEdges()
        {
            FaceEdge curFaceEdge = this;

            do
            {
                yield return(curFaceEdge);

                curFaceEdge = curFaceEdge.NextFaceEdge;
            } while (curFaceEdge != this);
        }
示例#6
0
        public IEnumerable <FaceEdge> RadialPrevFaceEdges()
        {
            FaceEdge curFaceEdge = this;

            do
            {
                yield return(curFaceEdge);

                curFaceEdge = curFaceEdge.radialPrevFaceEdge;
            } while (curFaceEdge != this);
        }
示例#7
0
        public FaceEdge(Face face, MeshEdge meshEdge, IVertex vertex)
        {
            this.ContainingFace = face;
            this.MeshEdge       = meshEdge;
            this.FirstVertex    = vertex;

            NextFaceEdge = null;
            PrevFaceEdge = null;

            RadialNextFaceEdge = radialPrevFaceEdge = this;
        }
示例#8
0
        public FaceEdge(Face face, MeshEdge meshEdge, Vertex vertex)
        {
            this.containingFace = face;
            this.meshEdge = meshEdge;
            this.firstVertex = vertex;

            nextFaceEdge = null;
            prevFaceEdge = null;

            radialNextFaceEdge = radialPrevFaceEdge = this;
        }
示例#9
0
        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;
                }
            }
        }
示例#10
0
        public IEnumerable <FaceEdge> FaceEdgesSharingMeshEdge()
        {
            FaceEdge curFaceEdge = this.firstFaceEdge;

            if (curFaceEdge != null)
            {
                do
                {
                    yield return(curFaceEdge);

                    curFaceEdge = curFaceEdge.RadialNextFaceEdge;
                } while (curFaceEdge != this.firstFaceEdge);
            }
        }
示例#11
0
        static public FaceEdgeTextureUvData Get(FaceEdge faceEdgeToGetTextureUvDataFor)
        {
            FaceEdgeTextureUvData plugin;

            faceEdgesWithTextureUvData.TryGetValue(faceEdgeToGetTextureUvDataFor, out plugin);

            if (plugin == null)
            {
                FaceEdgeTextureUvData newPlugin = new FaceEdgeTextureUvData();
                faceEdgesWithTextureUvData.Add(faceEdgeToGetTextureUvDataFor, newPlugin);

                return(newPlugin);
            }

            return(plugin);
        }
示例#12
0
        public void CalculateNormal()
        {
            FaceEdge faceEdge0       = firstFaceEdge;
            FaceEdge faceEdge1       = faceEdge0.NextFaceEdge;
            Vector3  faceEdge1Minus0 = faceEdge1.FirstVertex.Position - faceEdge0.FirstVertex.Position;
            FaceEdge faceEdge2       = faceEdge1;
            bool     collinear       = false;

            do
            {
                faceEdge2 = faceEdge2.NextFaceEdge;
                collinear = Vector3.Collinear(faceEdge0.FirstVertex.Position, faceEdge1.FirstVertex.Position, faceEdge2.FirstVertex.Position);
            } while (collinear && faceEdge2 != faceEdge0);
            Vector3 face2Minus0 = faceEdge2.FirstVertex.Position - faceEdge0.FirstVertex.Position;

            Normal = Vector3.Cross(faceEdge1Minus0, face2Minus0).GetNormal();
        }
示例#13
0
        public void ReverseFaceEdges(Face faceToReverse)
        {
            FaceEdge temp    = null;
            FaceEdge current = faceToReverse.firstFaceEdge;

            // swap next and prev for all nodes of
            // doubly linked list
            do
            {
                temp = current.prevFaceEdge;
                current.prevFaceEdge = current.nextFaceEdge;
                current.nextFaceEdge = temp;
                current = current.prevFaceEdge;                 // go to the next
            } while (current != faceToReverse.firstFaceEdge);

            faceToReverse.CalculateNormal();
        }
		static public FaceEdgeTextureUvData Get(FaceEdge faceEdgeToGetTextureUvDataFor)
		{
			FaceEdgeTextureUvData plugin = null;
			lock(faceEdgesWithTextureUvData)
			{
				faceEdgesWithTextureUvData.TryGetValue(faceEdgeToGetTextureUvDataFor, out plugin);

				if (plugin == null)
				{
					FaceEdgeTextureUvData newPlugin = new FaceEdgeTextureUvData();
					faceEdgesWithTextureUvData.Add(faceEdgeToGetTextureUvDataFor, newPlugin);

					return newPlugin;
				}
			}

			return plugin;
		}
示例#15
0
        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;
            }
        }
        static public FaceEdgeTextureUvData Get(FaceEdge faceEdgeToGetTextureUvDataFor)
        {
            FaceEdgeTextureUvData plugin = null;

            using (TimedLock.Lock(faceEdgesWithTextureUvData, "Get FaceEdgeTextureUvData"))
            {
                faceEdgesWithTextureUvData.TryGetValue(faceEdgeToGetTextureUvDataFor, out plugin);

                if (plugin == null)
                {
                    FaceEdgeTextureUvData newPlugin = new FaceEdgeTextureUvData();
                    faceEdgesWithTextureUvData.Add(faceEdgeToGetTextureUvDataFor, newPlugin);

                    return(newPlugin);
                }
            }

            return(plugin);
        }
示例#17
0
        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;
            }
        }
示例#18
0
		private void DrawFaceEdge(FaceEdge faceEdge, Vector2 faceAverageCenter)
		{
			Vector2 start = MoveTowardsCenter(GetImagePosition(faceEdge.firstVertex.Position), faceAverageCenter);
			Vector2 end = MoveTowardsCenter(GetImagePosition(faceEdge.nextFaceEdge.firstVertex.Position), faceAverageCenter);

			DrawEdgeLine(start, end, faceEdge.Data.ID.ToString(), faceEdgeColor);
			graphics.Circle(start, 3, RGBA_Bytes.Black);
			WriteStringAtPos("{0}".FormatWith(faceEdge.meshEdge.Data.ID), (start + end) / 2 + new Vector2(0, -12), meshEdgeColor);
			WriteStringAtPos("{0}".FormatWith(faceEdge.containingFace.Data.ID), (start + end) / 2 + new Vector2(0, 12), faceColor);

			Vector2 delta = end - start;
			Vector2 normal = delta.GetNormal();
			double length = delta.Length;
			Vector2 left = normal.GetPerpendicularLeft();

			// draw the starting vertex info
			WriteStringAtPos("{0}".FormatWith(faceEdge.firstVertex.Data.ID), start + normal * length * .10, vertexColor);

			// draw the next and prev faceEdge info
			WriteStringAtPos("{0}".FormatWith(faceEdge.nextFaceEdge.Data.ID), start + normal * length * .60, faceEdgeColor);
			WriteStringAtPos("{0}".FormatWith(faceEdge.prevFaceEdge.Data.ID), start + normal * length * .40, faceEdgeColor);

			// draw the radialFaceEdge info
			WriteStringAtPos("{0}".FormatWith(faceEdge.radialNextFaceEdge.Data.ID), start + new Vector2(0, 7) + normal * length * .90, faceEdgeColor);
			WriteStringAtPos("{0}".FormatWith(faceEdge.radialPrevFaceEdge.Data.ID), start + new Vector2(0, -7) + normal * length * .90, faceEdgeColor);
		}
示例#19
0
        public bool GetCutLine(Plane cutPlane, ref Vector3 start, ref Vector3 end)
        {
            int      splitCount   = 0;
            FaceEdge prevEdge     = null;
            bool     prevInFront  = false;
            bool     first        = true;
            FaceEdge firstEdge    = null;
            bool     firstInFront = false;

            foreach (FaceEdge faceEdge in FaceEdges())
            {
                if (first)
                {
                    prevEdge     = faceEdge;
                    prevInFront  = cutPlane.GetDistanceFromPlane(prevEdge.FirstVertex.Position) > 0;
                    first        = false;
                    firstEdge    = prevEdge;
                    firstInFront = prevInFront;
                }
                else
                {
                    FaceEdge curEdge    = faceEdge;
                    bool     curInFront = cutPlane.GetDistanceFromPlane(curEdge.FirstVertex.Position) > 0;
                    if (prevInFront != curInFront)
                    {
                        // we crossed over the cut line
                        Vector3 directionNormal = (curEdge.FirstVertex.Position - prevEdge.FirstVertex.Position).GetNormal();
                        Ray     edgeRay         = new Ray(prevEdge.FirstVertex.Position, directionNormal);
                        double  distanceToHit;
                        bool    hitFrontOfPlane;
                        if (cutPlane.RayHitPlane(edgeRay, out distanceToHit, out hitFrontOfPlane))
                        {
                            splitCount++;
                            if (splitCount == 1)
                            {
                                start = edgeRay.origin + edgeRay.directionNormal * distanceToHit;
                            }
                            else
                            {
                                end = edgeRay.origin + edgeRay.directionNormal * distanceToHit;
                            }
                        }
                    }

                    prevEdge    = curEdge;
                    prevInFront = curInFront;
                    if (splitCount == 2)
                    {
                        break;
                    }
                }
            }

            if (splitCount == 1 &&
                prevInFront != firstInFront)
            {
                // we crossed over the cut line
                Vector3 directionNormal = (firstEdge.FirstVertex.Position - prevEdge.FirstVertex.Position).GetNormal();
                Ray     edgeRay         = new Ray(prevEdge.FirstVertex.Position, directionNormal);
                double  distanceToHit;
                bool    hitFrontOfPlane;
                if (cutPlane.RayHitPlane(edgeRay, out distanceToHit, out hitFrontOfPlane))
                {
                    splitCount++;
                    end = edgeRay.origin + edgeRay.directionNormal * distanceToHit;
                }
            }

            if (splitCount == 2)
            {
                return(true);
            }

            return(false);
        }
示例#20
0
		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);
		}
示例#21
0
		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;
				}
			}
		}
示例#22
0
		private static void DeleteFaceEdge(FaceEdge faceEdgeToDelete)
		{
		}
示例#23
0
		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);
			}
		}
示例#24
0
        /// <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;
        }
示例#25
0
        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);
        }