Пример #1
0
        public static Mesh Cylinder(int segments, int slices, float radius, float height, Mesh m = null)
        {
            if (slices < 2)
            {
                throw new ArgumentException("Must be more than 2 slices");
            }

            height /= 2f;

            m = m ?? new Mesh();

            Vertex[][] sliceVerts = new Vertex[slices][];
            for (int i = 0; i < slices; i++)
            {
                sliceVerts[i] = new Vertex[segments];
            }

            float angle = 0;
            float step  = MathHelper.TwoPi / (float)segments;

            for (int segment = 0; segment < segments; segment++)
            {
                Vector2 xy = new Vector2((float)Math.Sin(angle), (float)Math.Cos(angle));

                for (int slice = 0; slice < slices; slice++)
                {
                    float l = slice / (float)slices;
                    float z = MathHelper.Lerp(-height, height, l);

                    sliceVerts[slice][segment] = m.GetVertex(new Vector3(xy, z), "slice:" + slice + " seg:" + segment);
                }

                angle += step;
            }

            m.GetFace(sliceVerts[0].Reverse());
            m.GetFace(sliceVerts[slices - 1]);

            for (int segment = 0; segment < segments; segment++)
            {
                for (int slice = 0; slice < slices - 1; slice++)
                {
                    m.GetFace(
                        sliceVerts[slice][segment],
                        sliceVerts[slice][(segment + 1) % segments],
                        sliceVerts[slice + 1][(segment + 1) % segments],
                        sliceVerts[slice + 1][segment]
                        );
                }
            }

            return(m);
        }
Пример #2
0
        public void MergeEdgesAroundALoneFace()
        {
            Mesh m = new Mesh();

            var a = m.GetVertex(new Vector3(0, 0, 1), "a");
            var b = m.GetVertex(new Vector3(0, 0, 2), "b");
            var c = m.GetVertex(new Vector3(0, 0, 3), "c");
            var d = m.GetVertex(new Vector3(0, 0, 4), "d");

            var abcd = m.GetFace(a, b, c, d);

            var ab = m.GetEdge(a, b);

            Assert.AreEqual(8, m.HalfEdges.Count());

            ab.Merge();

            Assert.AreEqual(c, ab.End);
            Assert.AreEqual(ab.Next, m.GetEdge(c, d, false));
            Assert.IsNull(m.GetEdge(a, b, false));
            Assert.AreEqual(ab, m.GetEdge(d, a, false).Next);

            Assert.AreEqual(6, m.HalfEdges.Count());
            Assert.AreEqual(3, m.HalfEdges.Where(e => e.Face == null).Count());
            Assert.AreEqual(0, m.HalfEdges.Where(e => e.Face != null && e.Next == null).Count());
            Assert.AreEqual(0, m.HalfEdges.Where(e => e.Face == null && e.Next != null).Count());
        }
Пример #3
0
        /// <summary>
        /// Replaces a face with a set of faces with 3 vertices
        /// </summary>
        /// <param name="f">The f.</param>
        /// <param name="m">The m.</param>
        public static void TriangulateMutator(Face f, Mesh m)
        {
            int c = 0;

            foreach (var v in f.Vertices)
            {
                c++;
                if (c > 3)
                {
                    break;
                }
            }
            if (c == 3)
            {
                return;
            }

            var verts = f.TriangulateFromSinglePoint.ToArray();

            f.Delete();

            for (int i = 0; i < verts.Length; i += 3)
            {
                m.GetFace(verts[i], verts[i + 1], verts[i + 2]);
            }
        }
Пример #4
0
        public void ConstructTriangle()
        {
            Mesh m = new Mesh();
            //oh hai
            var a = m.GetVertex(Vector3.Zero);
            var b = m.GetVertex(Vector3.Zero);
            var c = m.GetVertex(Vector3.Zero);

            var f = m.GetFace(a, b, c);
        }
Пример #5
0
        public void DeleteAndReplaceSurroundedFace()
        {
            Mesh m = new Mesh();

            var a = m.GetVertex(new Vector3(1, 0, 0));
            var abp = m.GetVertex(new Vector3(0, 1, 0));
            var b = m.GetVertex(new Vector3(2, 0, 0));
            var bcp = m.GetVertex(new Vector3(0, 2, 0));
            var c = m.GetVertex(new Vector3(3, 0, 0));
            var cap = m.GetVertex(new Vector3(0, 3, 0));

            var f = m.GetFace(a, b, c);
            var ab = m.GetFace(a, abp, b);
            var bc = m.GetFace(b, bcp, c);
            var ca = m.GetFace(c, cap, a);

            var fEdges = f.Edges.ToList();

            f.Delete();

            Assert.AreEqual(3, m.Faces.Count());

            foreach (var e in fEdges)
            {
                Assert.IsNull(e.Face);
                Assert.IsNull(e.Next);
            }

            foreach (var e in fEdges)
            {
                Assert.IsNotNull(e.Twin.Face);
                Assert.IsNotNull(e.Twin.Next);
            }

            f = m.GetFace(b, c, m.GetVertex(Vector3.Zero));
        }
Пример #6
0
        public static Mesh Icosahedron(Mesh m = null)
        {
            m = m ?? new Mesh();

            var vertices = icosahedronVertices.Select((a, i) => m.GetVertex(a, i.ToString())).ToArray();

            for (int i = 0; i < icosahedronIndices.Length; i += 3)
            {
                var a = vertices[icosahedronIndices[i + 2]];
                var b = vertices[icosahedronIndices[i + 1]];
                var c = vertices[icosahedronIndices[i]];

                Face f = m.GetFace(a, b, c);
            }

            return(m);
        }
Пример #7
0
        /// <summary>
        /// Inserts a midpoint into this face
        /// Deletes this face
        /// </summary>
        /// <param name="midpoint">The midpoint.</param>
        public void InsertMidpoint(Vertex midpoint)
        {
            Mesh.InformSplitMidpointBegin(this, midpoint);

            var edges = Edges.ToArray();

            Delete();

            for (int i = 0; i < edges.Length; i++)
            {
                var v1 = edges[i].End;
                var v2 = edges[(i + 1) % edges.Length].End;
                Mesh.GetFace(v1, v2, midpoint);
            }

            Mesh.InformSplitMidpointEnd(this, midpoint);
        }
Пример #8
0
        public static Mesh Icosahedron(Func<Vector3, Vertex> factory = null)
        {
            Mesh m = new Mesh(factory ?? defaultFactory);

            var vertices = icosahedronVertices.Select(a => m.GetVertex(a)).ToArray();

            for (int i = 0; i < icosahedronIndices.Length; i += 3)
            {
                var a = vertices[icosahedronIndices[i]];
                var b = vertices[icosahedronIndices[i + 1]];
                var c = vertices[icosahedronIndices[i + 2]];

                Face f = m.GetFace(a, b, c);
            }

            return m;
        }
Пример #9
0
        public void DeleteLoneFace()
        {
            Mesh m = new Mesh();

            var a = m.GetVertex(new Vector3(1, 0, 0));
            var b = m.GetVertex(new Vector3(2, 0, 0));
            var c = m.GetVertex(new Vector3(3, 0, 0));

            var f = m.GetFace(a, b, c);

            f.Delete();

            foreach (var edge in m.HalfEdges)
            {
                Assert.IsNull(edge.Face);
                Assert.IsNull(edge.Next);
                Assert.IsNull(edge.Twin.Face);
                Assert.IsNull(edge.Twin.Next);
            }

            Assert.AreEqual(0, m.Faces.Count());
        }
Пример #10
0
        /// <summary>
        /// Construct a cuboid graph on the given vertices, winding around { top1, top2, top3, top4 } and then all neighbours accordingly
        /// </summary>
        /// <param name="top1"></param>
        /// <param name="top2"></param>
        /// <param name="top3"></param>
        /// <param name="top4"></param>
        /// <param name="bottom1"></param>
        /// <param name="bottom2"></param>
        /// <param name="bottom3"></param>
        /// <param name="bottom4"></param>
        /// <param name="factory"></param>
        /// <returns></returns>
        public static Mesh Cuboid(Vector3 top1, Vector3 top2, Vector3 top3, Vector3 top4, Vector3 bottom1, Vector3 bottom2, Vector3 bottom3, Vector3 bottom4, Mesh m = null)
        {
            m = m ?? new Mesh();

            Vertex t1 = m.GetVertex(top1);
            Vertex t2 = m.GetVertex(top2);
            Vertex t3 = m.GetVertex(top3);
            Vertex t4 = m.GetVertex(top4);

            Vertex b5 = m.GetVertex(bottom1);
            Vertex b6 = m.GetVertex(bottom2);
            Vertex b7 = m.GetVertex(bottom3);
            Vertex b8 = m.GetVertex(bottom4);

            Face t1234  = m.GetFace(t4, t3, t2, t1);
            Face t21b56 = m.GetFace(b6, b5, t1, t2);
            Face t32b67 = m.GetFace(b7, b6, t2, t3);
            Face t43b78 = m.GetFace(b8, b7, t3, t4);
            Face t14b85 = m.GetFace(b5, b8, t4, t1);
            Face b6587  = m.GetFace(b7, b8, b5, b6);

            return(m);
        }
Пример #11
0
        public void GetSameFaceTwiceWithDifferentVertexIndices()
        {
            Mesh m = new Mesh();

            Vertex a = m.GetVertex(new Vector3(0, 0, 1));
            Vertex b = m.GetVertex(new Vector3(0, 0, 2));
            Vertex c = m.GetVertex(new Vector3(0, 0, 3));
            Vertex d = m.GetVertex(new Vector3(0, 0, 4));

            Face abcd = m.GetFace(a, b, c, d);
            Face bcda = m.GetFace(b, c, d, a);
            Face cdab = m.GetFace(c, d, a, b);
            Face dabc = m.GetFace(d, a, b, c);

            Assert.AreEqual(abcd, bcda);
            Assert.AreEqual(abcd, cdab);
            Assert.AreEqual(abcd, dabc);
        }
Пример #12
0
        /// <summary>
        /// Splits all the edges of each face, and connects each of the new vertices together
        /// </summary>
        /// <param name="m">The m.</param>
        /// <returns></returns>
        public static Mesh SubdivideInvertedFace(Mesh m)
        {
            var edges = new HashSet<HalfEdge>(m.HalfEdges.Where(a => a.Primary));
            foreach (var edge in edges)
                edge.Split(edge.End.Position * 0.5f + edge.Twin.End.Position * 0.5f);

            var faces = m.Faces.ToArray();
            List<HalfEdge> faceEdgesNewVertices = new List<HalfEdge>();
            Queue<Vertex> outerTriangles = new Queue<Vertex>();
            foreach (var face in faces)
            {
                faceEdgesNewVertices.Clear();
                outerTriangles.Clear();

                //when edges are split, the original edge is left pointing at the new vertex inserted in the middle
                //build a list of all the original edges in this face, which means the end vertices of these edges are the new vertices
                foreach (var edge in face.Edges)
                {
                    if (edges.Contains(edge)) //this edge ends in a new vertex
                        faceEdgesNewVertices.Add(edge);
                    else //this edge ends in an old vertex, find the next and previous vertex and queue them up to become a triangle
                    {
                        outerTriangles.Enqueue(edge.End);
                        outerTriangles.Enqueue(edge.Next.End);
                        outerTriangles.Enqueue(edge.Twin.End);
                    }
                }

                if (outerTriangles.Count % 3 != 0)
                    throw new InvalidOperationException("Queue length not divisible by three, not possible to construct triangles from this!");

                face.Delete();

                var central = m.GetFace(faceEdgesNewVertices.Select(e => e.End));

                while (outerTriangles.Count > 0)
                {
                    var a = outerTriangles.Dequeue();
                    var b = outerTriangles.Dequeue();
                    var c = outerTriangles.Dequeue();

                    m.GetFace(a, b, c);
                }
            }

            throw new NotImplementedException();
        }
Пример #13
0
        public void FacesEnumerator()
        {
            Mesh m = new Mesh();

            var a = m.GetVertex(new Vector3(1, 0, 0));
            var abp = m.GetVertex(new Vector3(0, 1, 0));
            var b = m.GetVertex(new Vector3(2, 0, 0));
            var bcp = m.GetVertex(new Vector3(0, 2, 0));
            var c = m.GetVertex(new Vector3(3, 0, 0));
            var cap = m.GetVertex(new Vector3(0, 3, 0));

            var f = m.GetFace(a, b, c);
            var ab = m.GetFace(a, abp, b);
            var bc = m.GetFace(b, bcp, c);
            var ca = m.GetFace(c, cap, a);

            var faces = f.Neighbours.ToArray();
            var abc = faces[0] == ab && faces[1] == bc && faces[2] == ca;
            var bca = faces[1] == ab && faces[2] == bc && faces[0] == ca;
            var cab = faces[2] == ab && faces[0] == bc && faces[1] == ca;

            Assert.IsTrue(abc ^ bca ^ cab);
        }
Пример #14
0
        public void EdgesEnumerator()
        {
            Mesh m = new Mesh();

            var a = m.GetVertex(new Vector3(1, 0, 0));
            var b = m.GetVertex(new Vector3(2, 0, 0));
            var c = m.GetVertex(new Vector3(3, 0, 0));

            var f = m.GetFace(a, b, c);

            var edges = f.Edges.ToArray();
            var abc = m.GetEdge(a, b) == edges[0] && m.GetEdge(b, c) == edges[1] && m.GetEdge(c, a) == edges[2];
            var bca = m.GetEdge(a, b) == edges[1] && m.GetEdge(b, c) == edges[2] && m.GetEdge(c, a) == edges[0];
            var cab = m.GetEdge(a, b) == edges[2] && m.GetEdge(b, c) == edges[0] && m.GetEdge(c, a) == edges[1];

            Assert.IsTrue(abc ^ bca ^ cab);
        }
Пример #15
0
        public void SplitHalfEdgeOnASingleFace()
        {
            Mesh m = new Mesh();

            var a = m.GetVertex(new Vector3(1, 0, 0), "a");
            var b = m.GetVertex(new Vector3(2, 0, 0), "b");
            var c = m.GetVertex(new Vector3(3, 0, 0), "c");

            var f = m.GetFace(a, b, c);

            var mid = m.GetVertex(new Vector3(4, 0, 0), "mid");
            var ab = m.GetEdge(a, b);
            ab.Split(mid);

            Assert.AreEqual(4, f.Edges.Count());
            Assert.AreEqual(4, f.Vertices.Count());
            Assert.AreEqual(0, f.Neighbours.Count());

            var ba = m.GetEdge(b, a);

            Assert.IsNull(ba.Face);
            Assert.IsNull(ba.Next);
        }
Пример #16
0
        public void VerticesEnumerator()
        {
            Mesh m = new Mesh();

            var a = m.GetVertex(new Vector3(1, 0, 0));
            var b = m.GetVertex(new Vector3(2, 0, 0));
            var c = m.GetVertex(new Vector3(3, 0, 0));

            var f = m.GetFace(a, b, c);

            var vertices = f.Vertices.ToArray();
            var abc = vertices[0] == a && vertices[1] == b && vertices[2] == c;
            var bca = vertices[1] == a && vertices[2] == b && vertices[0] == c;
            var cab = vertices[2] == a && vertices[0] == b && vertices[1] == c;

            Assert.IsTrue(abc ^ bca ^ cab);
        }
Пример #17
0
        public void SplitHalfEdgeBetweenTwoFaces()
        {
            Mesh m = new Mesh();

            var a = m.GetVertex(new Vector3(1, 0, 0), "a");
            var b = m.GetVertex(new Vector3(2, 0, 0), "b");
            var c = m.GetVertex(new Vector3(3, 0, 0), "c");
            var d = m.GetVertex(new Vector3(4, 0, 0), "d");

            Face abc = m.GetFace(a, b, c);
            Face bcd = m.GetFace(c, b, d);

            var bc = m.GetEdge(b, c);
            bc.Split(m.GetVertex(new Vector3(5, 0, 0), "m"));

            foreach (var face in m.Faces)
            {
                foreach (var edge in face.Edges)
                    Assert.AreEqual(edge.End, edge.Next.Twin.End);
            }

            Assert.AreEqual(4, abc.Edges.Count());
            Assert.AreEqual(1, abc.Neighbours.Count());
            Assert.AreEqual(4, abc.Vertices.Count());

            Assert.AreEqual(4, bcd.Edges.Count());
            Assert.AreEqual(1, bcd.Neighbours.Count());
            Assert.AreEqual(4, bcd.Vertices.Count());
        }
Пример #18
0
 public override void Undo(Mesh mesh, Stack<Change> changes)
 {
     var f = mesh.GetFace(Border.Select(a => mesh.GetVertex(a)));
 }
Пример #19
0
 public override void Undo(Mesh mesh, Stack<Change> changes)
 {
     mesh.GetFace(Border).Delete();
 }
Пример #20
0
        /// <summary>
        /// Construct a cuboid graph on the given vertices, winding around { top1, top2, top3, top4 } and then all neighbours accordingly
        /// </summary>
        /// <param name="top1"></param>
        /// <param name="top2"></param>
        /// <param name="top3"></param>
        /// <param name="top4"></param>
        /// <param name="bottom1"></param>
        /// <param name="bottom2"></param>
        /// <param name="bottom3"></param>
        /// <param name="bottom4"></param>
        /// <param name="factory"></param>
        /// <returns></returns>
        public static Mesh Cuboid(Vector3 top1, Vector3 top2, Vector3 top3, Vector3 top4, Vector3 bottom1, Vector3 bottom2, Vector3 bottom3, Vector3 bottom4, Mesh m = null)
        {
            m = m ?? new Mesh();

            Vertex t1 = m.GetVertex(top1);
            Vertex t2 = m.GetVertex(top2);
            Vertex t3 = m.GetVertex(top3);
            Vertex t4 = m.GetVertex(top4);

            Vertex b5 = m.GetVertex(bottom1);
            Vertex b6 = m.GetVertex(bottom2);
            Vertex b7 = m.GetVertex(bottom3);
            Vertex b8 = m.GetVertex(bottom4);

            Face t1234  = m.GetFace(t4, t3, t2, t1);
            Face t21b56 = m.GetFace(b6, b5, t1, t2);
            Face t32b67 = m.GetFace(b7, b6, t2, t3);
            Face t43b78 = m.GetFace(b8, b7, t3, t4);
            Face t14b85 = m.GetFace(b5, b8, t4, t1);
            Face b6587  = m.GetFace(b7, b8, b5, b6);

            return m;
        }
Пример #21
0
        public static Mesh Icosahedron(Mesh m = null)
        {
            m = m ?? new Mesh();

            var vertices = icosahedronVertices.Select((a, i) => m.GetVertex(a, i.ToString())).ToArray();

            for (int i = 0; i < icosahedronIndices.Length; i += 3)
            {
                var a = vertices[icosahedronIndices[i + 2]];
                var b = vertices[icosahedronIndices[i + 1]];
                var c = vertices[icosahedronIndices[i]];

                Face f = m.GetFace(a, b, c);
            }

            return m;
        }
Пример #22
0
        public static Mesh Cylinder(int segments, int slices, float radius, float height, Mesh m = null)
        {
            if (slices < 2)
                throw new ArgumentException("Must be more than 2 slices");

            height /= 2f;

            m = m ?? new Mesh();

            Vertex[][] sliceVerts = new Vertex[slices][];
            for (int i = 0; i < slices; i++)
                sliceVerts[i] = new Vertex[segments];

            float angle = 0;
            float step = MathHelper.TwoPi / (float)segments;
            for (int segment = 0; segment < segments; segment++)
            {
                Vector2 xy = new Vector2((float)Math.Sin(angle), (float)Math.Cos(angle));

                for (int slice = 0; slice < slices; slice++)
                {
                    float l = slice / (float)slices;
                    float z = MathHelper.Lerp(-height, height, l);

                    sliceVerts[slice][segment] = m.GetVertex(new Vector3(xy, z), "slice:" + slice + " seg:" + segment);
                }

                angle += step;
            }

            m.GetFace(sliceVerts[0].Reverse());
            m.GetFace(sliceVerts[slices - 1]);

            for (int segment = 0; segment < segments; segment++)
            {
                for (int slice = 0; slice < slices - 1; slice++)
                {
                    m.GetFace(
                        sliceVerts[slice][segment],
                        sliceVerts[slice][(segment + 1) % segments],
                        sliceVerts[slice + 1][(segment + 1) % segments],
                        sliceVerts[slice + 1][segment]
                    );
                }
            }

            return m;
        }
Пример #23
0
        public void InsertMidpoint()
        {
            Mesh m = new Mesh();

            var a = m.GetVertex(new Vector3(1, 0, 0));
            var b = m.GetVertex(new Vector3(2, 0, 0));
            var c = m.GetVertex(new Vector3(3, 0, 0));

            var f = m.GetFace(a, b, c);

            f.InsertMidpoint(m.GetVertex(new Vector3(4, 0, 0)));

            Assert.AreEqual(3, m.Faces.Count());
        }
Пример #24
0
        public void SplitEdgeCheckUpdatedIndices()
        {
            Mesh m = new Mesh();

            var a = m.GetVertex(new Vector3(1, 0, 0), "a");
            var b = m.GetVertex(new Vector3(2, 0, 0), "b");
            var c = m.GetVertex(new Vector3(3, 0, 0), "c");
            var d = m.GetVertex(new Vector3(4, 0, 0), "d");

            Face abc = m.GetFace(a, b, c);
            Face bcd = m.GetFace(c, b, d);

            var bc = m.GetEdge(b, c);
            var mid = m.GetVertex(new Vector3(5, 0, 0), "m");
            bc.Split(mid);

            Assert.AreEqual(2, mid.Neighbours.Count());
            Assert.IsTrue(mid.Neighbours.Contains(abc));
            Assert.IsTrue(mid.Neighbours.Contains(bcd));
        }