Example #1
0
    // split the face in the center
    // return the new Vertex
    public Vertex Split()
    {
        Vertex v = hmesh.CreateVertex();

        List <Halfedge> newHalfedges = new List <Halfedge>();
        List <Vertex>   vertices     = new List <Vertex>();

        // create double halfedges
        foreach (var he in Circulate())
        {
            v.position += he.vert.position;
            v.uv1      += he.vert.uv1;
            v.uv2      += he.vert.uv2;

            Halfedge toNewVertex   = hmesh.CreateHalfedge();
            Halfedge fromNewVertex = hmesh.CreateHalfedge();
            toNewVertex.Glue(fromNewVertex);
            newHalfedges.Add(toNewVertex);
            vertices.Add(he.vert);
        }
        int count = 0;


        // second iteration - link everything together
        foreach (var he in Circulate())
        {
            Vertex   prevVertex     = vertices[(count - 1 + newHalfedges.Count) % newHalfedges.Count];
            Vertex   nextVertex     = vertices[count];
            Halfedge prevNewOppEdge = newHalfedges[(count - 1 + newHalfedges.Count) % newHalfedges.Count].opp;
            Halfedge newEdge        = newHalfedges[count];
            // link halfedges
            newEdge.Link(prevNewOppEdge);
            prevNewOppEdge.Link(he);
            he.Link(newEdge);

            // link vertices
            newEdge.vert        = v;
            v.halfedge          = prevNewOppEdge;
            prevNewOppEdge.vert = prevVertex;

            bool first = count == 0;
            Face f     = he.face;
            if (!first)
            {
                f = hmesh.CreateFace();
            }
            f.halfedge = he;
            f.ReassignFaceToEdgeLoop();

            count++;
        }

        v.position = v.position * (1.0f / count);       // set average position
        v.uv1      = v.uv1 * (1.0f / count);
        v.uv2      = v.uv2 * (1.0f / count);

        return(v);
    }
Example #2
0
    // Creates a new vertex inside the face and connect it to the cutFrom vertex using two halfedges.
    // Note that this function leaves the face in an invalid state, since the new halfedges will have face == opp.face.
    public Vertex CutInto(Vertex cutFrom, Vector3 pos)
    {
        Debug.Assert(cutFrom.hmesh == hmesh);
        Halfedge cutFromEdge = null;

        foreach (var e in Circulate())
        {
            if (e.vert == cutFrom)
            {
                cutFromEdge = e;
            }
        }
        if (cutFromEdge == null)
        {
            Debug.LogError("Cannot find vertex in face");
            return(null);
        }

        Vertex newVertex = hmesh.CreateVertex();

        newVertex.position = pos;
        Halfedge he1 = hmesh.CreateHalfedge();
        Halfedge he2 = hmesh.CreateHalfedge();

        he1.Glue(he2);

        Halfedge cutFromEdgeNext = cutFromEdge.next;

        cutFromEdge.Link(he1);
        he1.Link(he2);
        he2.Link(cutFromEdgeNext);

        he1.Link(this);
        he2.Link(this);
        he1.vert           = newVertex;
        newVertex.halfedge = he1.next;
        Debug.Assert(newVertex.halfedge != null);
        he2.vert         = cutFrom;
        cutFrom.halfedge = he2.next;

        return(newVertex);
    }
Example #3
0
    // Cut the face in two parts. Assumes that the face is convex
    public Face Cut(Vertex v1, Vertex v2)
    {
        Debug.Assert(v1.hmesh == hmesh);
        Debug.Assert(v2.hmesh == hmesh);
        Debug.Assert(v1.halfedge != null);
        Debug.Assert(v2.halfedge != null);
        Debug.Assert(v1 != v2);
        Halfedge v1He = null;
        Halfedge v2He = null;

        foreach (var he in Circulate())
        {
            if (he.vert == v1)
            {
                v1He = he;
            }
            else if (he.vert == v2)
            {
                v2He = he;
            }
        }
        if (v1He == null || v2He == null)
        {
            Debug.LogError("Cannot find vertices for split");
            return(null);
        }
        Debug.Assert(v1He != v2He);
        Halfedge v1HeNext = v1He.next;
        Halfedge v2HeNext = v2He.next;
        Face     f        = hmesh.CreateFace();
        Halfedge he1      = hmesh.CreateHalfedge();
        Halfedge he2      = hmesh.CreateHalfedge();

        he1.Glue(he2);

        v1He.Link(he1);
        he1.Link(v2HeNext);
        v2He.Link(he2);
        he2.Link(v1HeNext);
        he1.vert = v2;
        he2.vert = v1;

        halfedge = he1;
        ReassignFaceToEdgeLoop();

        f.halfedge = he2;
        f.ReassignFaceToEdgeLoop();

        v1.halfedge = v1HeNext;
        v2.halfedge = v2HeNext;

        return(f);
    }
Example #4
0
    // If boundary vertex Dissolve face.
    // Otherwise return false
    public bool Dissolve()
    {
        List <Halfedge> hes = Circulate();

        if (!IsBoundary())
        {
            return(false);
        }
        if (hes.Count == 1)
        {
            var faceEdges = halfedge.face.Circulate();
            if (faceEdges.Count > 2)
            {
                Halfedge oldHe = halfedge;
                Halfedge prev  = halfedge.prev;
                Halfedge next  = halfedge.next;
                prev.Link(next);
                prev.vert           = oldHe.vert;
                oldHe.face.halfedge = prev;
                hmesh.Destroy(oldHe);
                hmesh.Destroy(this);
            }
            else
            {
                halfedge.face.Dissolve2Edges();
            }
        }
        else if (hes.Count == 2)
        {
            foreach (var he in hes)
            {
                if (he.opp != null)
                {
                    var newPos = he.vert.positionD;
                    var vertex = he.Collapse();
                    vertex.positionD = newPos;
                    return(true);
                }
            }
        }
        else
        {
            // iterate each neighbour face
            foreach (var faceHe in hes)
            {
                faceHe.face.Dissolve();
            }
        }
        return(true);
    }
Example #5
0
    // Cut the face in two parts. Assumes that the face is convex
    // The new face is always created as the one that contains vertices between v1 and v2
    public Face Cut(Vertex v1, Vertex v2)
    {
        Debug.Assert(v1.hmesh == hmesh);
        Debug.Assert(v2.hmesh == hmesh);
        Debug.Assert(v1.halfedge != null);
        Debug.Assert(v2.halfedge != null);
        Debug.Assert(v1 != v2);
        Halfedge v1He  = null;
        Halfedge v2He  = null;
        var      edges = Circulate();

        Debug.Assert(edges.Count > 3);
        foreach (var he in edges)
        {
            if (he.vert == v1)
            {
                v1He = he;
            }
            else if (he.vert == v2)
            {
                v2He = he;
            }
        }

        if (v1He == null || v2He == null)
        {
            if (v1He == null)
            {
                Debug.Log("Could not find first parameter");
            }
            if (v2He == null)
            {
                Debug.Log("Could not find second parameter");
            }
            return(null);
        }
        Debug.Assert(v1He != v2He);
        if (v1He.prev.vert == v2)
        {
            Debug.LogWarning("face " + id + " cut adjacent vertices " + v1 + " to " + v2);
            return(this);
        }
        if (v2He.prev.vert == v1)
        {
            Debug.LogWarning("face " + id + " cut adjacent vertices " + v1 + " to " + v2);
            return(this);
        }
        Halfedge v1HeNext = v1He.next;
        Halfedge v2HeNext = v2He.next;
        Face     f        = hmesh.CreateFace();
        Halfedge he1      = hmesh.CreateHalfedge();
        Halfedge he2      = hmesh.CreateHalfedge();

        he1.Glue(he2);

        v1He.Link(he1);
        he1.Link(v2HeNext);
        v2He.Link(he2);
        he2.Link(v1HeNext);
        he1.vert = v2;
        he2.vert = v1;

        halfedge = he1;
        ReassignFaceToEdgeLoop();

        f.halfedge = he2;
        f.ReassignFaceToEdgeLoop();

        return(f);
    }
Example #6
0
    public void Build(Mesh mesh, Matrix4x4 transform, int submesh = 0)
    {
        if (mesh.GetTopology(0) != MeshTopology.Triangles)
        {
            Debug.LogError("Only triangles supported.");
        }

        Dictionary <ulong, Halfedge> halfedgeByVertexID = new Dictionary <ulong, Halfedge>();

        // Create a list of (HMesh) Vertices
        var           meshVertices = mesh.vertices;
        var           meshUv       = mesh.uv;
        var           meshUv2      = mesh.uv2;
        List <Vertex> vertexList   = new List <Vertex>(meshVertices.Length);
        bool          hasUv1       = meshUv != null && meshUv.Length == meshVertices.Length;
        bool          hasUv2       = meshUv2 != null && meshUv2.Length == meshVertices.Length;

        for (int i = 0; i < meshVertices.Length; i++)
        {
            var newV = CreateVertex();
            newV.position = transform.MultiplyPoint(meshVertices[i]);
            if (hasUv1)
            {
                newV.uv1 = meshUv[i];
            }
            if (hasUv2)
            {
                newV.uv2 = meshUv2[i];
            }
            vertexList.Add(newV);
        }


        // create faces and half edges
        var meshTriangles = mesh.GetTriangles(submesh);

        for (int i = 0; i < meshTriangles.Length; i += 3)
        {
            int[] idx = new int[] {
                meshTriangles[i],
                meshTriangles[i + 1],
                meshTriangles[i + 2]
            };
            Halfedge[] edges = new Halfedge[3];
            Face       face  = CreateFace();
            for (int j = 0; j < 3; j++)
            {
                Halfedge edge = CreateHalfedge();
                edge.Link(face);
                edges[j] = edge;
            }
            for (int j = 0; j < 3; j++)
            {
                int from = idx[j];
                int to   = idx[(j + 1) % 3];
                edges[j].Link(edges[(j + 1) % 3]);
                edges[j].vert = vertexList[to];
                edges[j].vert.label++;
                ulong edgeId = EdgeKey(from, to);
                if (halfedgeByVertexID.ContainsKey(edgeId))
                {
                    var oldEdge = halfedgeByVertexID[edgeId];

                    Debug.LogError("Edge old edge from " + oldEdge.vert.position + " to " + oldEdge.prev.vert.position);
                    Debug.LogError("Edge already exists from " + vertexList[to].position + " to " + vertexList[from].position);
                }
                halfedgeByVertexID.Add(edgeId, edges[j]);
            }
        }
        for (int i = vertexList.Count - 1; i >= 0; i--)
        {
            if (vertexList[i].label == 0)
            {
                Destroy(vertexList[i]);
            }
        }
        int glued = 0;

        // glue all opposite half edges
        for (int i = 0; i < meshTriangles.Length; i += 3)
        {
            int[] idx =
            {
                meshTriangles[i],
                meshTriangles[i + 1],
                meshTriangles[i + 2]
            };
            for (int j = 0; j < 3; j++)
            {
                int      from            = idx[j];
                int      to              = idx[(j + 1) % 3];
                ulong    key             = EdgeKey(from, to);
                ulong    oppKey          = EdgeKey(to, from);
                Halfedge edge            = halfedgeByVertexID[key];
                bool     isOppUnassigned = edge.opp == null;
                if (isOppUnassigned && key < oppKey && halfedgeByVertexID.ContainsKey(oppKey))
                {
                    Halfedge oppEdge = halfedgeByVertexID[oppKey];
                    edge.Glue(oppEdge);
                    glued++;
                }
            }
        }

        SplitNonManifoldVertices();
    }
Example #7
0
    public void Build(Mesh mesh, Matrix4x4 transform)
    {
        if (mesh.subMeshCount != 1)
        {
            Debug.LogError("Invalid mesh.subMeshCount. Must be 1.");
        }
        if (mesh.GetTopology(0) != MeshTopology.Triangles)
        {
            Debug.LogError("Only triangles supported.");
        }
        List <Vertex> vertexList = new List <Vertex>();
        Dictionary <uint, Halfedge> halfedgeByVertexID = new Dictionary <uint, Halfedge>();

        // Create a list of (HMesh) Vertices
        bool hasUv1 = mesh.uv != null && mesh.uv.Length == mesh.vertices.Length;
        bool hasUv2 = mesh.uv2 != null && mesh.uv2.Length == mesh.vertices.Length;

        for (int i = 0; i < mesh.vertices.Length; i++)
        {
            var newV = CreateVertex();
            newV.position = transform.MultiplyPoint(mesh.vertices[i]);
            if (hasUv1)
            {
                newV.uv1 = mesh.uv[i];
            }
            if (hasUv2)
            {
                newV.uv2 = mesh.uv2[i];
            }
            vertexList.Add(newV);
        }

        // create faces and half edges
        for (int i = 0; i < mesh.triangles.Length; i += 3)
        {
            int[] idx = new int[] {
                mesh.triangles[i],
                mesh.triangles[i + 1],
                mesh.triangles[i + 2]
            };
            Halfedge[] edges = new Halfedge[3];
            Face       face  = CreateFace();
            for (int j = 0; j < 3; j++)
            {
                Halfedge edge = CreateHalfedge();
                edge.Link(face);
                edges[j] = edge;
            }
            for (int j = 0; j < 3; j++)
            {
                int from = idx[j];
                int to   = idx[(j + 1) % 3];
                edges[j].Link(edges[(j + 1) % 3]);
                edges[j].vert           = vertexList[to];
                vertexList[to].halfedge = edges[j].next;
                uint edgeId = EdgeKey(from, to);
                halfedgeByVertexID.Add(edgeId, edges[j]);
            }
        }
        int glued = 0;

        // glue all opposite half edges
        for (int i = 0; i < mesh.triangles.Length; i += 3)
        {
            int[] idx = new int[] {
                mesh.triangles[i],
                mesh.triangles[i + 1],
                mesh.triangles[i + 2]
            };
            for (int j = 0; j < 3; j++)
            {
                int      from            = idx[j];
                int      to              = idx[(j + 1) % 3];
                uint     key             = EdgeKey(from, to);
                uint     oppKey          = EdgeKey(to, from);
                Halfedge edge            = halfedgeByVertexID[key];
                bool     isOppUnassigned = edge.opp == null;
                if (isOppUnassigned && halfedgeByVertexID.ContainsKey(oppKey))
                {
                    Halfedge oppEdge = halfedgeByVertexID[oppKey];
                    edge.Glue(oppEdge);
                    glued++;
                }
            }
        }
    }