/// <summary>
        /// Create a MeshGeometryVisual3D from an existing HalfEdgeMesh with specified Colors.
        /// </summary>
        /// <param name="mesh">The existing HalfEdgeMesh.</param>
        /// <param name="foreground">The Color for the Triangles of the Mesh.</param>
        /// <param name="backGround">The Background Color for the Triangles of the Mesh.</param>
        /// <returns>MeshVisual3D of the HalfEdgeMesh with the specified Materials.</returns>
        private static MeshVisual3D CreateVisual3DWithoutNormals(this HalfEdgeMesh mesh,
                                                                 Material frontMaterial, Material backMaterial)
        {
            if (frontMaterial == default(Material))
            {
                frontMaterial = new DiffuseMaterial(new SolidColorBrush(DefaultForegroundColor));
            }
            if (backMaterial == default(Material))
            {
                backMaterial = new DiffuseMaterial(new SolidColorBrush(DefaultBackgroundColor));
            }

            var mesh3D = new Mesh3D(mesh.Vertices.Select(p => new Point3D(p.X, p.Y, p.Z)), mesh.Triangles.Where(t => t.HalfEdge != null).SelectMany(t => t.VertexIndizes));

            var meshVisual = new MeshVisual3D()
            {
                Mesh             = mesh3D,
                FaceMaterial     = frontMaterial,
                FaceBackMaterial = backMaterial,
                EdgeDiameter     = 0,
                VertexRadius     = 0
            };

            return(meshVisual);
        }
Esempio n. 2
0
    void Start()
    {
        this.heMesh = Main.heMesh;
        MeshFilter meshFilter = GetComponent <MeshFilter>();

        meshFilter.mesh = heMesh.convertToMesh();
    }
Esempio n. 3
0
 public void AddFace_NonManifold_ShouldThrowException()
 {
     var vertices = new[] { new Point3D(0, 0, 0), new Point3D(1, 0, 0), new Point3D(1, 1, 0), new Point3D(0, 1, 0) };
     var mesh = new HalfEdgeMesh(vertices);
     mesh.AddFace(0, 1, 2);
     mesh.AddFace(0, 1, 2);
 }
        /// <summary>
        /// Create a MeshGeometryVisual3D from an existing HalfEdgeMesh with specified Colors.
        /// </summary>
        /// <param name="mesh">The existing HalfEdgeMesh.</param>
        /// <param name="foreground">The Color for the Triangles of the Mesh.</param>
        /// <param name="backGround">The Background Color for the Triangles of the Mesh.</param>
        /// <returns>MeshGeometryVisual3D of the HalfEdgeMesh with the specified Materials.</returns>
        private static MeshGeometryVisual3D CreateVisual3DWithNormals(this HalfEdgeMesh mesh,
                                                                      Material frontMaterial, Material backMaterial)
        {
            if (frontMaterial == default(Material))
            {
                frontMaterial = new DiffuseMaterial(new SolidColorBrush(DefaultForegroundColor));
            }
            if (backMaterial == default(Material))
            {
                backMaterial = new DiffuseMaterial(new SolidColorBrush(DefaultBackgroundColor));
            }

            var mesh3D = new MeshGeometry3D();

            mesh3D.Positions       = new Point3DCollection(mesh.Vertices.Select(p => new Point3D(p.X, p.Y, p.Z)));
            mesh3D.TriangleIndices = new Int32Collection(mesh.Triangles.SelectMany(t => t.VertexIndizes));
            if (mesh.HasNormals)
            {
                mesh3D.Normals = new Vector3DCollection(mesh.Vertices.Select(v => new Vector3D(v.Normal.X, v.Normal.Y, v.Normal.Z)));
            }

            var meshVisual = new MeshGeometryVisual3D()
            {
                MeshGeometry = mesh3D,
                Material     = frontMaterial,
                BackMaterial = backMaterial
            };

            return(meshVisual);
        }
Esempio n. 5
0
    private void OnValidate()
    {
        foreach (Transform obj in transform)
        {
            StartCoroutine(Destroy(obj.gameObject));
        }

        GameObject   newObj = new GameObject("Cube");
        var          mesh   = MeshScript.GetNewMesh(Vector3.up, vertexWidth, vertexHeight, Color.black);
        HalfEdgeMesh heMesh = null;

        Vector3[] directions = { Vector3.down, Vector3.back, Vector3.forward, Vector3.right, Vector3.left };
        foreach (var dir in directions)
        {
            var meshIter = MeshScript.GetNewMesh(dir, vertexWidth, vertexHeight, Color.black);
            heMesh = HalfEdgeMesh.CombineMeshes(ref mesh, meshIter);
        }

        var meshScript = newObj.AddComponent <MeshScript>();

        newObj.transform.parent = transform;
        newObj.AddComponent <MeshRenderer>().sharedMaterial = meshMaterial;
        newObj.AddComponent <MeshFilter>().sharedMesh       = mesh;
        meshScript.mesh         = mesh;
        meshScript.localUp      = Vector3.up;
        meshScript.vertexHeight = vertexHeight;
        meshScript.vertexWidth  = vertexWidth;
        meshScript.initMesh();
        meshScript.heMesh = heMesh;
    }
Esempio n. 6
0
        private static HalfEdgeMesh CreateTriangulatedQuadMesh()
        {
            var vertices        = new[] { new Point3D(0, 0, 0), new Point3D(1, 0, 0), new Point3D(1, 1, 0), new Point3D(0, 1, 0) };
            var triangleIndices = new[] { 0, 1, 2, 2, 3, 0 };
            var mesh            = new HalfEdgeMesh(vertices, triangleIndices);

            return(mesh);
        }
Esempio n. 7
0
        public void AddFace_NonManifold_ShouldThrowException()
        {
            var vertices = new[] { new Point3D(0, 0, 0), new Point3D(1, 0, 0), new Point3D(1, 1, 0), new Point3D(0, 1, 0) };
            var mesh     = new HalfEdgeMesh(vertices);

            mesh.AddFace(0, 1, 2);
            mesh.AddFace(0, 1, 2);
        }
Esempio n. 8
0
        /// <summary>
        /// Generate a HalfEdgeMesh of a Cube.
        /// </summary>
        /// <param name="origin">The Origin of the Cube.</param>
        /// <param name="size">The Size of the Cube.</param>
        /// <param name="sides">Defines which Sides of the Cube should be generated (default = All Sides).</param>
        /// <param name="calculateNormals">Calculate Vertex Normals or not.</param>
        /// <returns>The generated HalfEdgeMesh.</returns>
        public static HalfEdgeMesh GenerateCube(Vector origin,
                                                float size = 1, CubeSides sides = CubeSides.All, bool calculateNormals = false)
        {
            var vertices = new List <Vertex>()
            {
                new Vertex(origin.X, origin.Y, origin.Z),
                new Vertex(1 * size + origin.X, origin.Y, origin.Z),
                new Vertex(1 * size + origin.X, 1 * size + origin.Y, origin.Z),
                new Vertex(origin.X, 1 * size + origin.Y, origin.Z),
                new Vertex(origin.X, origin.Y, 1 * size + origin.Z),
                new Vertex(1 * size + origin.X, origin.Y, 1 * size + origin.Z),
                new Vertex(1 * size + origin.X, 1 * size + origin.Y, 1 * size + origin.Z),
                new Vertex(origin.X, 1 * size + origin.Y, 1 * size + origin.Z),
            };

            var triangles = new List <Triangle>();

            if (sides.HasFlag(CubeSides.NegativeZ))
            {
                triangles.Add(new Triangle(0, 2, 1));
                triangles.Add(new Triangle(0, 3, 2));
            }
            if (sides.HasFlag(CubeSides.PositiveZ))
            {
                triangles.Add(new Triangle(4, 5, 6));
                triangles.Add(new Triangle(4, 6, 7));
            }
            if (sides.HasFlag(CubeSides.NegativeY))
            {
                triangles.Add(new Triangle(0, 1, 5));
                triangles.Add(new Triangle(0, 5, 4));
            }
            if (sides.HasFlag(CubeSides.PositiveX))
            {
                triangles.Add(new Triangle(1, 2, 6));
                triangles.Add(new Triangle(1, 6, 5));
            }
            if (sides.HasFlag(CubeSides.PositiveY))
            {
                triangles.Add(new Triangle(2, 3, 7));
                triangles.Add(new Triangle(2, 7, 6));
            }
            if (sides.HasFlag(CubeSides.NegativeX))
            {
                triangles.Add(new Triangle(3, 0, 4));
                triangles.Add(new Triangle(3, 4, 7));
            }

            var mesh = new HalfEdgeMesh(vertices, triangles);

            if (calculateNormals)
            {
                mesh.CalculateVertexNormals();
            }

            return(mesh);
        }
Esempio n. 9
0
 public void AddFace_Quad()
 {
     var vertices = new[] { new Point3D(0, 0, 0), new Point3D(1, 0, 0), new Point3D(1, 1, 0), new Point3D(0, 1, 0) };
     var mesh = new HalfEdgeMesh(vertices);
     mesh.AddFace(0, 1, 2, 3);
     Assert.AreEqual(1, mesh.Faces.Count);
     Assert.AreEqual(4, mesh.Edges.Count);
     Assert.AreEqual(4, mesh.Vertices.Count);
 }
Esempio n. 10
0
        public void AddFace_Quad()
        {
            var vertices = new[] { new Point3D(0, 0, 0), new Point3D(1, 0, 0), new Point3D(1, 1, 0), new Point3D(0, 1, 0) };
            var mesh     = new HalfEdgeMesh(vertices);

            mesh.AddFace(0, 1, 2, 3);
            Assert.AreEqual(1, mesh.Faces.Count);
            Assert.AreEqual(4, mesh.Edges.Count);
            Assert.AreEqual(4, mesh.Vertices.Count);
        }
 /// <summary>
 /// Depending of the HalfEdgeMesh's <see cref="HalfEdgeMesh.HalfEdges"/> Property, a MeshGeometryVisual3D or a MeshVisual3D is generated.
 /// </summary>
 /// <param name="mesh">The HalfEdgeMesh.</param>
 /// <param name="frontMaterial">The front Material.</param>
 /// <param name="backMaterial">The back Material.</param>
 /// <returns></returns>
 public static ModelVisual3D CreateVisual3D(this HalfEdgeMesh mesh,
                                            Material frontMaterial, Material backMaterial)
 {
     if (mesh.HasNormals)
     {
         return(CreateVisual3DWithNormals(mesh, frontMaterial, backMaterial));
     }
     else
     {
         return(CreateVisual3DWithoutNormals(mesh, frontMaterial, backMaterial));
     }
 }
Esempio n. 12
0
        public static UnionFind <VertexNode> MakeUnionFind(HalfEdgeMesh mesh)
        {
            UnionFind <VertexNode> uf = new UnionFind <VertexNode>(mesh.Vertices.Length);

            Matrix <double>[] faceQuadrics = new Matrix <double> [mesh.Faces.Length];
            for (int i = 0; i < faceQuadrics.Length; i++)
            {
                Face f = mesh.Faces[i];
                if (f.IsBoundary)
                {
                    continue;
                }
                Vector3 normal = f.Normal;
                Vector3 v1     = f.anyHalfEdge.tailVertex.position;

                float d = -Vector3.Dot(v1, normal);

                Vector <double> v = DenseVector.OfArray(new double[] { normal.x, normal.y, normal.z, d });

                faceQuadrics[i] = v.OuterProduct(v);
            }

            for (int i = 0; i < uf.NumNodes; i++)
            {
                VertexNode current = uf[i];
                current.position     = mesh.Vertices[i].position;
                current.containingUF = uf;

                ErrorQuadric vertQuadric = new ErrorQuadric();

                // Iterate over all faces surrounding this vertex and sum up the face quadrics
                HalfEdge start = mesh.Vertices[i].anyHalfEdge;
                HalfEdge he    = start;
                do
                {
                    Face f = he.face;
                    if (!f.IsBoundary)
                    {
                        Matrix <double> faceQuadric = faceQuadrics[he.face.Index];
                        vertQuadric.AddQuadric(faceQuadric);
                    }
                    he = he.flip.next;
                }while (he != start);

                current.quadric      = vertQuadric;
                current.mergedPoints = new HashSet <int>();
                current.mergedPoints.Add(i);
                current.Index = i;
            }

            return(uf);
        }
Esempio n. 13
0
 void Awake()
 {
     rnd = new System.Random();
     //heMesh = HalfEdgeMesh.makeFromFile("Assets/Meshes/tetrahedron.halfedge");
     heMesh    = HalfEdgeMesh.makeFromFile("Assets/Meshes/icosahedron.halfedge");
     nutrition = new Dictionary <int, float>();
     foreach (int ix in heMesh.vertices.Keys)
     {
         nutrition[ix] = 0.0f;
     }
     //heMesh = HalfEdgeMesh.makeFromFile("Assets/Meshes/pentakis_decodahedron.halfedge");
     Debug.Log("HalfEdgeMesh: " + heMesh.halfEdges.Count + " " + heMesh.vertices.Count + " " + heMesh.edges.Count + " " + heMesh.faces.Count);
 }
Esempio n. 14
0
        private HalfEdgeMesh CreateUnitCubeMesh()
        {
            var vertices = new[]
            {
                new Point3D(0, 0, 0), new Point3D(1, 0, 0), new Point3D(1, 1, 0), new Point3D(0, 1, 0),
                new Point3D(0, 0, 1), new Point3D(1, 0, 1), new Point3D(1, 1, 1), new Point3D(0, 1, 1)
            };
            var mesh = new HalfEdgeMesh(vertices);

            mesh.AddFace(3, 2, 1, 0);
            mesh.AddFace(4, 5, 6, 7);
            mesh.AddFace(0, 1, 5, 4);
            mesh.AddFace(1, 2, 6, 5);
            mesh.AddFace(2, 3, 7, 6);
            mesh.AddFace(3, 0, 4, 7);
            return(mesh);
        }
    public static void DrawHalfEdgeGizmos(HalfEdgeMesh heMesh, bool halfEdges, bool vertices, bool faces)
    {
        if (heMesh != null)
        {
            if (halfEdges)
            {
                foreach (var he in heMesh.halfEdges)
                {
                    var originPos = he.origin.data.pos;
                    var toPos     = he.next.origin.data.pos;

                    DrawArrow(originPos, toPos - originPos, .05f, 10f);
                }
            }

            if (vertices)
            {
                foreach (var vertex in heMesh.vertices)
                {
                    Gizmos.color = vertex.data.color;
                    Gizmos.DrawSphere(vertex.data.pos, .02f);
                    Gizmos.color = Color.white;
                }
            }

            if (faces)
            {
                foreach (var face in heMesh.faces)
                {
                    Vector3 sum      = new Vector3();
                    Color   colorSum = new Color();
                    foreach (var he in face.GetAdjacentHalfEdges())
                    {
                        sum      += he.origin.data.pos;
                        colorSum += he.origin.data.color;
                    }
                    sum         /= 3;
                    colorSum    /= 3;
                    Gizmos.color = colorSum;
                    Gizmos.DrawSphere(sum, .02f);
                    Gizmos.color = Color.white;
                }
            }
        }
    }
Esempio n. 16
0
 // Use this for initialization
 void Start()
 {
     if (mesh == null)
     {
         mesh = GetComponent <MeshFilter>().sharedMesh;
         if (!mesh.name.EndsWith("copy"))
         {
             mesh      = GetComponent <MeshFilter>().sharedMesh.CopyMesh();
             mesh.name = name + "_copy";
             GetComponent <MeshFilter>().sharedMesh = mesh;
         }
     }
     if (heMesh == null)
     {
         heMesh = mesh.HEMesh();
         if (heMesh == null)
         {
             //mesh.startGetHEMesh();
         }
     }
 }
        /// <summary>
        /// Create a LinesVisual3D from the Border Information of an existing HalfEdgeMesh.
        /// </summary>
        /// <param name="mesh">The existing HalfEdgeMesh.</param>
        /// <param name="lineColor">The Line Color.</param>
        /// <param name="thickness">The Line Thickness of the Border Lines.</param>
        /// <returns>LinesVisual3D representing the Boundary of the HalfEdgeMesh if the <paramref name="lineColor"/> is not closed.</returns>
        public static LinesVisual3D CreateBoundaryVisual3D(this HalfEdgeMesh mesh, Color lineColor, double thickness = 2)
        {
            if (mesh.IsClosed)
            {
                return(null);
            }

            if (lineColor == default(Color))
            {
                lineColor = DefaultHighlightColor;
            }

            var borderVertices = new Point3DCollection(mesh.BoundaryVertices.Select(p => new Point3D(p.X, p.Y, p.Z)));
            var lineVisual     = new LinesVisual3D
            {
                Points      = borderVertices,
                Color       = lineColor,
                Thickness   = thickness,
                DepthOffset = Offset
            };

            return(lineVisual);
        }
Esempio n. 18
0
        /// <summary>
        /// Generate a HalfEdgeMesh from an existing MeshGeometry3D Object.
        /// </summary>
        /// <param name="meshGeometry">The existing MeshGeometry3D Object.</param>
        /// <param name="calculateNormals">Calculate Vertex Normals or not.</param>
        /// <returns>The generated HalfEdgeMesh.</returns>
        public static HalfEdgeMesh GenerateFromMeshGeometry3D(MeshGeometry3D meshGeometry, bool calculateNormals = false)
        {
            var vertices  = meshGeometry.Positions.Select(p => new Vertex((float)p.X, (float)p.Y, (float)p.Z)).ToList();
            var triangles = new List <Triangle>();

            for (int i = 0; i < meshGeometry.TriangleIndices.Count; i += 3)
            {
                triangles.Add(new Triangle(meshGeometry.TriangleIndices.ElementAt(i),
                                           meshGeometry.TriangleIndices.ElementAt(i + 1),
                                           meshGeometry.TriangleIndices.ElementAt(i + 2)));
            }

            var mesh = new HalfEdgeMesh();

            mesh.AddVertices(vertices);
            mesh.AddTriangles(triangles);

            if (calculateNormals)
            {
                mesh.CalculateVertexNormals();
            }

            return(mesh);
        }
        // Use this for initialization
        void Start()
        {
            if (!meshFilter)
            {
                meshFilter = GetComponentInChildren <MeshFilter>();
            }
            heMesh = GetComponent <HalfEdgeMesh>();

            triangles = new List <Triangle>();
            edgeToTri = new Dictionary <EdgePair, Triangle>();

            mesh = meshFilter.mesh;
            int numTriangles = mesh.triangles.Length / 3;

            for (int i = 0; i < numTriangles; i++)
            {
                Triangle t = new Triangle(mesh.triangles[3 * i],
                                          mesh.triangles[3 * i + 1],
                                          mesh.triangles[3 * i + 2], i);
                triangles.Add(t);

                edgeToTri.Add(new EdgePair(mesh.triangles[3 * i + 0], mesh.triangles[3 * i + 1]), t);
                edgeToTri.Add(new EdgePair(mesh.triangles[3 * i + 1], mesh.triangles[3 * i + 2]), t);
                edgeToTri.Add(new EdgePair(mesh.triangles[3 * i + 2], mesh.triangles[3 * i + 0]), t);
            }

            identifiedPoints = new HashSet <int> [mesh.vertices.Length];
            for (int i = 0; i < mesh.vertices.Length; i++)
            {
                HashSet <int> init = new HashSet <int>();
                init.Add(i);
                identifiedPoints[i] = init;
            }

            doCollapse = false;
        }
 void Start()
 {
     doCollapse = false;
     heMesh     = GetComponent <HalfEdgeMesh>();
     mesh       = GetComponentInChildren <MeshFilter>().mesh;
 }
Esempio n. 21
0
 private static HalfEdgeMesh CreateUnitCube()
 {
     var vertices = new[]
         {
             new Point3D(0, 0, 0), new Point3D(1, 0, 0), new Point3D(1, 1, 0), new Point3D(0, 1, 0),
             new Point3D(0, 0, 1), new Point3D(1, 0, 1), new Point3D(1, 1, 1), new Point3D(0, 1, 1)
         };
     var mesh = new HalfEdgeMesh(vertices);
     mesh.AddFace(3, 2, 1, 0);
     mesh.AddFace(4, 5, 6, 7);
     mesh.AddFace(0, 1, 5, 4);
     mesh.AddFace(1, 2, 6, 5);
     mesh.AddFace(2, 3, 7, 6);
     mesh.AddFace(3, 0, 4, 7);
     return mesh;
 }
Esempio n. 22
0
 private static HalfEdgeMesh CreateTriangulatedQuadMesh()
 {
     var vertices = new[] { new Point3D(0, 0, 0), new Point3D(1, 0, 0), new Point3D(1, 1, 0), new Point3D(0, 1, 0) };
     var triangleIndices = new[] { 0, 1, 2, 2, 3, 0 };
     var mesh = new HalfEdgeMesh(vertices, triangleIndices);
     return mesh;
 }
 public Visual3DViewModel(HalfEdgeMesh mesh, Visual3D visual3D, string name)
 {
     _mesh     = mesh;
     _visual3D = visual3D;
     _name     = name;
 }
Esempio n. 24
0
 /// <summary>
 /// Abstract Constructor, initializes basic Properties
 /// </summary>
 public AbstractMeshElement()
 {
     _triangleMesh = null;
     _index        = -1;
 }
Esempio n. 25
0
    public static HalfEdgeMesh makeFromFile(string path)
    {
        List <string> lines = new List <string>();
        HalfEdgeMesh  mesh  = new HalfEdgeMesh();

        try
        {
            using (StreamReader reader = new StreamReader(path))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    lines.Add(line);
                }
            }
        }
        catch (Exception e)
        {
            Debug.LogError(e.Message);
        }

        // First pass, create empty elements
        foreach (String line in lines)
        {
            int id = Int32.Parse(line.Split(' ')[1]);
            if (line.StartsWith("halfedge"))
            {
                mesh.halfEdges[id] = new HalfEdge {
                    id = id
                };
            }
            else if (line.StartsWith("vertex"))
            {
                mesh.vertices[id] = new Vertex {
                    id = id
                };
            }
            else if (line.StartsWith("edge"))
            {
                mesh.edges[id] = new Edge {
                    id = id
                };
            }
            else if (line.StartsWith("face"))
            {
                mesh.faces[id] = new Face {
                    id = id
                };
            }
        }

        // Second pass, set connections
        foreach (String line in lines)
        {
            string[] split = line.Split(' ');

            int id = Int32.Parse(split[1]);

            if (line.StartsWith("halfedge"))
            {
                int nextHalfEdgeId = Int32.Parse(split[2]);
                int twinHalfEdgeId = Int32.Parse(split[3]);
                int vertexId       = Int32.Parse(split[4]);
                int edgeId         = Int32.Parse(split[5]);
                int faceId         = Int32.Parse(split[6]);

                mesh.halfEdges[id].next   = mesh.halfEdges[nextHalfEdgeId];
                mesh.halfEdges[id].twin   = mesh.halfEdges[twinHalfEdgeId];
                mesh.halfEdges[id].vertex = mesh.vertices[vertexId];
                mesh.halfEdges[id].edge   = mesh.edges[edgeId];
                mesh.halfEdges[id].face   = mesh.faces[faceId];
            }
            else if (line.StartsWith("vertex"))
            {
                int   halfEdgeId = Int32.Parse(split[2]);
                float x          = (float)Double.Parse(split[3]);
                float y          = (float)Double.Parse(split[4]);
                float z          = (float)Double.Parse(split[5]);
                mesh.vertices[id].halfEdge = mesh.halfEdges[halfEdgeId];
                mesh.vertices[id].position = new Vector3(x, y, z);
            }
            else if (line.StartsWith("edge"))
            {
                int halfEdgeId = Int32.Parse(split[2]);
                mesh.edges[id].halfEdge = mesh.halfEdges[halfEdgeId];
            }
            else if (line.StartsWith("face"))
            {
                int halfEdgeId = Int32.Parse(split[2]);
                mesh.faces[id].halfEdge = mesh.halfEdges[halfEdgeId];
            }
        }

        return(mesh);
    }
Esempio n. 26
0
        /// <summary>
        /// Generate a HalfEdgeMesh of a Sphere.
        /// </summary>
        /// <param name="center">The Center of the Sphere.</param>
        /// <param name="radius">The Radius of the Sphere.</param>
        /// <param name="numSides">Number of Sides of the Sphere (multiply by 4 for one Ring).</param>
        /// <param name="sides">Which Sides of the Sphere should be generated.</param>
        /// <param name="calculateNormals">Calculate Vertex Normals or not.</param>
        /// <returns>The generated HalfEdgeMesh.</returns>
        public static HalfEdgeMesh GenerateSphere(Vector center,
                                                  float radius = 1, int numSides = 8, CubeSides sides = CubeSides.All, bool calculateNormals = false)
        {
            var shiftVector     = Vector.One * 0.5f;
            var mesh            = new HalfEdgeMesh();
            var sideLength      = 1f / numSides;
            var verticesPerSide = numSides + 1;
            var vertices        = new List <Vertex>();

            var bottomVertices = new List <Vertex>(verticesPerSide * verticesPerSide);
            var topVertices    = new List <Vertex>(verticesPerSide * verticesPerSide);
            var frontVertices  = new List <Vertex>(verticesPerSide * verticesPerSide);
            var backVertices   = new List <Vertex>(verticesPerSide * verticesPerSide);
            var leftVertices   = new List <Vertex>(verticesPerSide * verticesPerSide);
            var rightVertices  = new List <Vertex>(verticesPerSide * verticesPerSide);
            var idx            = 0;

            for (int z = 0; z <= numSides; z++)
            {
                for (int y = 0; y <= numSides; y++)
                {
                    for (int x = 0; x <= numSides; x++)
                    {
                        if (z == 0 || z == numSides || x == 0 || x == numSides || y == 0 || y == numSides)
                        {
                            var vertex = new Vertex(x * sideLength - 0.5f, y * sideLength - 0.5f, z * sideLength - 0.5f)
                            {
                                Index = idx,
                            };
                            if (x == 0 && sides.HasFlag(CubeSides.NegativeZ))
                            {
                                bottomVertices.Add(vertex);
                            }
                            else if (x == numSides && sides.HasFlag(CubeSides.PositiveZ))
                            {
                                topVertices.Add(vertex);
                            }

                            if (y == 0 && sides.HasFlag(CubeSides.NegativeY))
                            {
                                frontVertices.Add(vertex);
                            }
                            else if (y == numSides && sides.HasFlag(CubeSides.PositiveY))
                            {
                                backVertices.Add(vertex);
                            }

                            if (z == 0 && sides.HasFlag(CubeSides.NegativeX))
                            {
                                leftVertices.Add(vertex);
                            }
                            else if (z == numSides && sides.HasFlag(CubeSides.PositiveX))
                            {
                                rightVertices.Add(vertex);
                            }

                            vertices.Add(vertex);
                            idx++;
                        }
                        else
                        {
                            x += numSides - 2;
                        }
                    }
                }
            }

            foreach (var vertex in vertices)
            {
                var vertexVector = (Vector)vertex;
                vertexVector.Normalize();
                vertex.Position = vertexVector * radius + center;
            }
            mesh.AddVertices(vertices);

            var triangles = new List <Triangle>();

            for (int i = 0; i < numSides * numSides; i++)
            {
                idx = i + i / numSides;
                var nextIdx        = idx + 1;
                var nextRowIdx     = nextIdx + numSides;
                var nextRowNextIdx = nextRowIdx + 1;
                if (sides.HasFlag(CubeSides.NegativeZ))
                {
                    mesh.AddTriangle(new Triangle(bottomVertices[idx].Index, bottomVertices[nextRowNextIdx].Index, bottomVertices[nextIdx].Index));
                    mesh.AddTriangle(new Triangle(bottomVertices[idx].Index, bottomVertices[nextRowIdx].Index, bottomVertices[nextRowNextIdx].Index));
                }

                if (sides.HasFlag(CubeSides.PositiveZ))
                {
                    mesh.AddTriangle(new Triangle(topVertices[idx].Index, topVertices[nextIdx].Index, topVertices[nextRowNextIdx].Index));
                    mesh.AddTriangle(new Triangle(topVertices[idx].Index, topVertices[nextRowNextIdx].Index, topVertices[nextRowIdx].Index));
                }

                if (sides.HasFlag(CubeSides.NegativeY))
                {
                    mesh.AddTriangle(new Triangle(frontVertices[idx].Index, frontVertices[nextIdx].Index, frontVertices[nextRowNextIdx].Index));
                    mesh.AddTriangle(new Triangle(frontVertices[idx].Index, frontVertices[nextRowNextIdx].Index, frontVertices[nextRowIdx].Index));
                }

                if (sides.HasFlag(CubeSides.PositiveY))
                {
                    mesh.AddTriangle(new Triangle(backVertices[idx].Index, backVertices[nextRowNextIdx].Index, backVertices[nextIdx].Index));
                    mesh.AddTriangle(new Triangle(backVertices[idx].Index, backVertices[nextRowIdx].Index, backVertices[nextRowNextIdx].Index));
                }

                if (sides.HasFlag(CubeSides.NegativeX))
                {
                    mesh.AddTriangle(new Triangle(leftVertices[idx].Index, leftVertices[nextRowNextIdx].Index, leftVertices[nextIdx].Index));
                    mesh.AddTriangle(new Triangle(leftVertices[idx].Index, leftVertices[nextRowIdx].Index, leftVertices[nextRowNextIdx].Index));
                }

                if (sides.HasFlag(CubeSides.PositiveX))
                {
                    mesh.AddTriangle(new Triangle(rightVertices[idx].Index, rightVertices[nextIdx].Index, rightVertices[nextRowNextIdx].Index));
                    mesh.AddTriangle(new Triangle(rightVertices[idx].Index, rightVertices[nextRowNextIdx].Index, rightVertices[nextRowIdx].Index));
                }
            }

            if (calculateNormals)
            {
                mesh.CalculateVertexNormals();
            }

            return(mesh);
        }
Esempio n. 27
0
 public MainWindow()
 {
     InitializeComponent();
     DataContext = this;
     this.Mesh   = CreateUnitCubeMesh();
 }
Esempio n. 28
0
    public void CutWithPlane(Plane plane)
    {
        float      sTime = Time.realtimeSinceStartup;
        GameObject child = gameObject.transform.GetChild(0).gameObject;

        meshFilter = child.GetComponent <MeshFilter>();
        mesh       = meshFilter.mesh;
        InitHalfEdgeMesh();
        bool[]          visited      = new bool[heMesh.halfEdges.Count];
        List <HalfEdge> newHalfEdges = new List <HalfEdge>();
        int             s            = heMesh.halfEdges.Count;
        int             rightCount   = 0;
        int             leftCount    = 0;
        Vector3         newVertCoord = Vector3.zero;
        int             onCount      = 0;

        /*
         * Dictionary<Vector3, Vector2> uvMap = new Dictionary<Vector3, Vector2>();
         * List<Vector2> uvs = new List<Vector2>();
         * mesh.GetUVs(0, uvs);
         * for (int i = 0; i < mesh.vertices.Length; i++)
         * {
         *  if (!uvMap.ContainsKey(mesh.vertices[i])) {
         *      uvMap.Add(mesh.vertices[i], uvs[i]);
         *  }
         * }*/
        for (int i = 0; i < s; i++)
        {
            if (visited[i])
            {
                continue;
            }
            // mark this and the opposite as visited
            HalfEdge he    = heMesh.halfEdges[i];
            HalfEdge heOpp = heMesh.halfEdges[he.oppositeIndex];
            visited[he.index]    = true;
            visited[heOpp.index] = true;

            // Check if intersection with plane
            Vector3 v0 = heMesh.vertices[he.verIndex].v;
            Vector3 v1 = heMesh.vertices[heOpp.verIndex].v;

            // First Set vertex plane config
            Vector3 c0     = v0 - plane.point;
            Vector3 c1     = v1 - plane.point;
            float   c0_dot = Vector3.Dot(c0, plane.normal);
            float   c1_dot = Vector3.Dot(c1, plane.normal);
            float   eps    = 0.0001f;
            if (Mathf.Abs(c0_dot) < eps)
            {
                heMesh.vertices[he.verIndex].config = PlaneConfig.On;
            }
            else if (c0_dot <= -eps)
            {
                heMesh.vertices[he.verIndex].config = PlaneConfig.Right;
                rightCount++;
            }
            else if (c0_dot >= eps)
            {
                heMesh.vertices[he.verIndex].config = PlaneConfig.Left;
                leftCount++;
            }
            if (Mathf.Abs(c1_dot) < eps)
            {
                heMesh.vertices[heOpp.verIndex].config = PlaneConfig.On;
            }
            else if (c1_dot <= -eps)
            {
                rightCount++;
                heMesh.vertices[heOpp.verIndex].config = PlaneConfig.Right;
            }
            else if (c1_dot >= eps)
            {
                leftCount++;
                heMesh.vertices[heOpp.verIndex].config = PlaneConfig.Left;
            }

            float   t;
            Vector3 iPoint = Plane.LinePlaneIntersect(plane, v0, v1, out t);
            if (t > 1.0f - eps || t < 0.0f + eps)
            {
                // No intersection on line segment OR parallel with plane
                continue;
            }
            // Debug.Log(t);
            // add new intersection vertex to half-edge structure
            HEVertex iVert = new HEVertex();
            iVert.v       = iPoint;
            onCount      += 1;
            newVertCoord += iPoint;
            iVert.heIndex = (short)heMesh.halfEdges.Count;
            iVert.config  = PlaneConfig.On;
            heMesh.vertices.Add(iVert);
            HalfEdge[] newHEs = HalfEdge.CreateFromTwo(he, heOpp, (short)heMesh.halfEdges.Count, (short)(heMesh.vertices.Count - 1));
            heMesh.halfEdges.Add(newHEs[0]);
            heMesh.halfEdges.Add(newHEs[1]);
            iPoints.Add(iPoint);
        }
        if (leftCount == 0 || rightCount == 0)
        {
            // Do nothing!!!!
            return;
        }
        heMesh.Triangulate();
        HalfEdgeMesh rightMesh = new HalfEdgeMesh();
        HalfEdgeMesh leftMesh  = new HalfEdgeMesh();

        heMesh.SplitInLeftAndRightMesh(leftMesh, rightMesh);

        GameObject         copy      = Instantiate(objectToCopy);
        GameObject         childCopy = copy.transform.GetChild(0).gameObject;
        SliceableWithPlane copyDebug = copy.GetComponent <SliceableWithPlane>();

        newVertCoord /= (float)onCount;

        rightMesh.CapClipPlane(plane.normal, newVertCoord);
        copyDebug.heMesh          = rightMesh;
        copyDebug.meshFilter      = childCopy.GetComponent <MeshFilter>();
        copyDebug.meshFilter.mesh = rightMesh.GetMesh();
        //  MeshFilter mfCpy = copy.GetComponent<MeshFilter>();
        leftMesh.CapClipPlane(-plane.normal, newVertCoord);
        meshFilter.mesh = leftMesh.GetMesh();

        /*
         * List<Vector2> newUVs = new List<Vector2>();
         * foreach (Vector3 v in meshFilter.mesh.vertices)
         * {
         *  if (!uvMap.ContainsKey(v))
         *  {
         *      newUVs.Add(Vector2.zero);
         *  } else
         *  {
         *      newUVs.Add(uvMap[v]);
         *  }
         * }
         * meshFilter.mesh.SetUVs(0, newUVs);
         */
        copyDebug.cutPlane = cutPlane;
        //heMesh.CreateStructureFromMesh(mesh);
        //copyDebug.heMesh.CreateStructureFromMesh(copyDebug.meshFilter.mesh);
        child.GetComponent <MeshCollider>().sharedMesh = null;
        child.GetComponent <MeshCollider>().sharedMesh = meshFilter.mesh;

        childCopy.GetComponent <MeshCollider>().sharedMesh = null;
        childCopy.GetComponent <MeshCollider>().sharedMesh = copyDebug.meshFilter.mesh;
        //  child.GetComponent<MeshCollider>().gameObject.SetActive(true);
        float eTime = Time.realtimeSinceStartup - sTime;

        Debug.Log("Time taken = " + eTime);
    }
Esempio n. 29
0
 public void InitHalfEdgeMesh()
 {
     heMesh = new HalfEdgeMesh(mesh);
 }
Esempio n. 30
0
 void Start()
 {
     this.heMesh = Main.heMesh;
     cellPrefab  = parameters.cellPrefab;
     cellObjs    = new Dictionary <int, GameObject>();
 }
Esempio n. 31
0
    // Every face should be a triangle! So call Triangulate first
    public void SplitInLeftAndRightMesh(HalfEdgeMesh left, HalfEdgeMesh right)
    {
        // Have to re-index everything :(
        Dictionary <Vector3, short> leftVertDict  = new Dictionary <Vector3, short>();
        Dictionary <Vector3, short> rightVertDict = new Dictionary <Vector3, short>();

        // First add the vertices, and get their indices
        short lVertIdx = 0;
        short rVertIdx = 0;

        foreach (HEVertex v in vertices)
        {
            HEVertex newVL = new HEVertex {
                v = v.v, heIndex = v.heIndex
            };
            HEVertex newVR = new HEVertex {
                v = v.v, heIndex = v.heIndex
            };
            if (v.config == PlaneConfig.Left)
            {
                newVL.config = PlaneConfig.Left;
                leftVertDict.Add(v.v, lVertIdx);
                left.vertices.Add(newVL);
                lVertIdx++;
            }
            else if (v.config == PlaneConfig.Right)
            {
                newVR.config = PlaneConfig.Right;
                rightVertDict.Add(v.v, rVertIdx);
                right.vertices.Add(newVR);
                rVertIdx++;
            }
            else
            {
                newVR.config = PlaneConfig.On;
                newVL.config = PlaneConfig.On;
                leftVertDict.Add(v.v, lVertIdx);
                left.vertices.Add(newVL);
                lVertIdx++;
                rightVertDict.Add(v.v, rVertIdx);
                right.vertices.Add(newVR);
                rVertIdx++;
            }
        }
        // The dicts should map old idx -> new idx...
        Dictionary <short, short> leftEdgeIdxMap  = new Dictionary <short, short>();
        Dictionary <short, short> rightEdgeIdxMap = new Dictionary <short, short>();
        Dictionary <short, short> leftFaceIdxMap  = new Dictionary <short, short>();
        Dictionary <short, short> rightFaceIdxMap = new Dictionary <short, short>();
        int lEdgeIdx = 0;
        int lFaceIdx = 0;
        int rEdgeIdx = 0;
        int rFaceIdx = 0;

        // Build the idx maps
        foreach (HalfEdge h in halfEdges)
        {
            PlaneConfig pConfig = GetFaceConfig(faces[h.faceIndex]);
            if (pConfig == PlaneConfig.Left)
            {
                leftEdgeIdxMap.Add(h.index, (short)lEdgeIdx);
                left.halfEdges.Add(h.Copy());
                lEdgeIdx++;
                if (!leftFaceIdxMap.ContainsKey(h.faceIndex))
                {
                    left.faces.Add(faces[h.faceIndex].Copy());
                    left.faces[lFaceIdx].heIndex = (short)(lEdgeIdx - 1);
                    leftFaceIdxMap.Add(h.faceIndex, (short)lFaceIdx);
                    lFaceIdx++;
                }
            }
            else if (pConfig == PlaneConfig.Right)
            {
                rightEdgeIdxMap.Add(h.index, (short)rEdgeIdx);
                right.halfEdges.Add(h.Copy());
                rEdgeIdx++;
                if (!rightFaceIdxMap.ContainsKey(h.faceIndex))
                {
                    right.faces.Add(faces[h.faceIndex].Copy());
                    right.faces[rFaceIdx].heIndex = (short)(rEdgeIdx - 1);
                    rightFaceIdxMap.Add(h.faceIndex, (short)rFaceIdx);
                    rFaceIdx++;
                }
            }
            else   // On, not possible for a face?
            {
                // ...
            }
        }
        // Update all the indices and stuff
        // Edge case is if both vertices are ON the plane, then they don't have an opposite edge
        // I think I will leave it and deal with it when triangulating the cap
        foreach (KeyValuePair <short, short> kvp in leftEdgeIdxMap)
        {
            // The edge
            left.halfEdges[kvp.Value].faceIndex = leftFaceIdxMap[halfEdges[kvp.Key].faceIndex];
            left.halfEdges[kvp.Value].nextIndex = leftEdgeIdxMap[halfEdges[kvp.Key].nextIndex];
            left.halfEdges[kvp.Value].verIndex  = leftVertDict[vertices[halfEdges[kvp.Key].verIndex].v];
            left.halfEdges[kvp.Value].index     = kvp.Value;
            // face done in loop above

            // Update vertices edge index, doesn't matter if we overwrite
            left.vertices[left.halfEdges[kvp.Value].verIndex].heIndex = kvp.Value;
        }
        foreach (KeyValuePair <short, short> kvp in rightEdgeIdxMap)
        {
            // The edge
            right.halfEdges[kvp.Value].faceIndex = rightFaceIdxMap[halfEdges[kvp.Key].faceIndex];
            right.halfEdges[kvp.Value].nextIndex = rightEdgeIdxMap[halfEdges[kvp.Key].nextIndex];
            right.halfEdges[kvp.Value].verIndex  = rightVertDict[vertices[halfEdges[kvp.Key].verIndex].v];
            right.halfEdges[kvp.Value].index     = kvp.Value;
            // face done in loop above

            // Update vertices edge index, doesn't matter if we overwrite
            right.vertices[right.halfEdges[kvp.Value].verIndex].heIndex = kvp.Value;
        }
    }
Esempio n. 32
0
    public static HalfEdgeMesh LoadMesh(Mesh mesh)
    {
        var heMesh = new HalfEdgeMesh();
        var map    = new Dictionary <Tuple <int, int>, HalfEdge>();

        for (var i = 0; i < mesh.vertexCount; i++)
        {
            heMesh.vertices.Add(new Vertex(i, new VertexData(mesh.vertices[i], Color.black)));
        }

        if (mesh.colors.Length == mesh.vertexCount)
        {
            for (var i = 0; i < mesh.vertexCount; i++)
            {
                heMesh.vertices[i].data.color = mesh.colors[i];
            }
        }
        if (mesh.uv.Length == mesh.vertexCount)
        {
            for (var i = 0; i < mesh.vertexCount; i++)
            {
                heMesh.vertices[i].data.uv = mesh.uv[i];
            }
        }

        for (var i = 0; i < mesh.triangles.Length; i += 3)
        {
            heMesh.faces.Add(new Face(i / 3, new FaceData(mesh.triangles[i],
                                                          mesh.triangles[i + 1],
                                                          mesh.triangles[i + 2])));
        }

        var index = 0;

        foreach (var face in heMesh.faces)
        {
            HalfEdge last  = null;
            HalfEdge first = null;
            for (var i = 0; i < 3; i++)
            {
                HalfEdge he;

                var key = new Tuple <int, int>(heMesh.vertices[face.data.vertices[i]].id, heMesh.vertices[face.data.vertices[(i + 1) % 3]].id);
                if (map.ContainsKey(key))
                {
                    he = map[key];
                    map.Remove(key);
                }
                else
                {
                    he = new HalfEdge(index++);
                    var hePair = new HalfEdge(index++);
                    heMesh.halfEdges.Add(he);
                    heMesh.halfEdges.Add(hePair);

                    he.pair     = hePair;
                    hePair.pair = he;

                    map.Add(new Tuple <int, int>(heMesh.vertices[face.data.vertices[(i + 1) % 3]].id, heMesh.vertices[face.data.vertices[i]].id), hePair);
                }

                he.face   = face;
                he.origin = heMesh.vertices[face.data.vertices[i]];
                he.prev   = last;
                if (first == null)
                {
                    first = he;
                }
                if (last != null)
                {
                    last.next = he;
                }
                last = he;

                heMesh.vertices[face.data.vertices[i]].halfEdge = he;
                face.halfEdge = he;
            }

            first.prev = last;
            last.next  = first;
        }

        foreach (var halfEdgePair in map)
        {
            halfEdgePair.Value.pair.pair = null;
            heMesh.halfEdges.Remove(halfEdgePair.Value);
        }
        map.Clear();

        return(heMesh);
    }
 void Start()
 {
     mesh = GetComponent <HalfEdgeMesh>();
 }