/**
         * Build neighbourly relations between vertices and wedges using the triangles of the model
         **/
        private void BuildNeighbourlyRelations(List <Wedge> wedges, Vertex[] vertices, int[] tris)
        {
            for (int i = 0; i != tris.Length; i += 3)
            {
                Vertex v0 = vertices[tris[i]];
                Vertex v1 = vertices[tris[i + 1]];
                Vertex v2 = vertices[tris[i + 2]];

                Triangle triangle = new Triangle(v0, v1, v2);

                //Set this triangle as an adjacent triangle for every vertex
                v0.AddAdjacentTriangle(triangle);
                v1.AddAdjacentTriangle(triangle);
                v2.AddAdjacentTriangle(triangle);

                Wedge w0 = GetWedgeHoldingVertex(wedges, v0);
                Wedge w1 = GetWedgeHoldingVertex(wedges, v1);
                Wedge w2 = GetWedgeHoldingVertex(wedges, v2);
                w0.AddNeighbor(w1);
                w0.AddNeighbor(w2);
                w1.AddNeighbor(w0);
                w1.AddNeighbor(w2);
                w2.AddNeighbor(w0);
                w2.AddNeighbor(w1);
            }
        }
Beispiel #2
0
 public void AddNeighbor(Wedge neighbor)
 {
     if (!HasNeighbor(neighbor))
     {
         m_neighbors.Add(neighbor);
     }
 }
Beispiel #3
0
        private void BuildWedges(List <Wedge> wedges, List <Vector3> verts, List <int> tris)
        {
            Vertex[] vertices = new Vertex[verts.Count];

            //First sort vertices into wedges
            for (int i = 0; i != verts.Count; i++)
            {
                Vertex vertex = new Vertex(verts[i], i);
                vertices[i] = vertex;

                Wedge wedge = WedgeForPosition(wedges, verts[i]);
                if (wedge != null)
                {
                    wedge.AddVertex(vertex);
                }
                else
                {
                    wedge = new Wedge(verts[i], wedges.Count);
                    wedge.AddVertex(vertex);
                    wedges.Add(wedge);
                }
            }

            //Build neighbourly relations between vertices and wedges using the triangles of the model
            BuildNeighbourlyRelations(wedges, vertices, tris);

            //Determine which triangles are adjacent to each wedge
            //for (int i = 0; i != m_wedges.Count; i++)
            //{
            //    m_wedges[i].InvalidateAdjacentTriangles();
            //}
        }
Beispiel #4
0
 public void RemoveNeighbor(Wedge neighbor)
 {
     if (HasNeighbor(neighbor))
     {
         m_neighbors.Remove(neighbor);
     }
 }
Beispiel #5
0
        }                                     // orthogonal unit vector

        public WedgeTriangle(Wedge w0, Wedge w1, Wedge w2)
        {
            m_wedges    = new Wedge[3];
            m_wedges[0] = w0;
            m_wedges[1] = w1;
            m_wedges[2] = w2;

            ComputeNormal();
        }
Beispiel #6
0
        /**
         * Collapse all vertices in this wedge using the m_mappedVertices list
         **/
        public void CollapseOnWedge(Wedge w)
        {
            //w = m_collapse;

            //collapsed vertices
            Vertex[] collapseVertices  = new Vertex[m_collapsedVertices.Count];
            int      collapseVertexIdx = 0;

            foreach (KeyValuePair <int, int> kvp in m_collapsedVertices)
            {
                Vertex vertex = GetVertexForID(kvp.Key);

                Vertex collapseVertex = w.GetVertexForID(kvp.Value);
                vertex.CollapseOnWedgeVertex(collapseVertex);

                collapseVertices[collapseVertexIdx] = collapseVertex;
                collapseVertexIdx++;
            }

            for (int i = 0; i != collapseVertices.Length; i++)
            {
                Vertex collapseVertex = collapseVertices[i];

                //the collapse vertex does not have any adjacent triangles even after collapsing operation, delete it
                if (collapseVertex.AdjacentTriangles.Count == 0)
                {
                    w.RemoveVertex(collapseVertex);
                    this.m_deletedVertices.Add(collapseVertex.ID);
                }
            }

            //for (int i = 0; i != m_collapsedVertices.Count; i++)
            //{
            //    Vertex vertex = GetVertexForID(m_collapsedVertices[i].m_initialIndex);

            //    //if (vertex != null) //vertex has been deleted
            //    Vertex collapseVertex = w.GetVertexForID(m_collapsedVertices[i].m_collapsedIndex);
            //    vertex.CollapseOnWedgeVertex(collapseVertex);

            //    //the collapse vertex does not have any adjacent triangles even after collapsing operation, delete it
            //    if (collapseVertex.AdjacentTriangles.Count == 0)
            //    {
            //        w.RemoveVertex(collapseVertex);
            //        this.m_deletedVertices.Add(collapseVertex.ID);
            //    }
            //}

            //displaced vertices
            for (int i = 0; i != m_displacedVertices.Count; i++)
            {
                Vertex vertex = GetVertexForID(m_displacedVertices[i].m_index);

                //if (vertex != null)
                w.AddVertex(vertex);
                this.RemoveVertex(vertex);
            }
        }
Beispiel #7
0
        /**
         * Compute the cost to collapse a specific edge defined by vertices u and v
         * **/
        private float ComputeEdgeCollapseCost(Wedge u, Wedge v)
        {
            // if we collapse edge uv by moving u to v then how
            // much different will the model change, i.e. how much "error".
            // Texture, vertex normal, and border vertex code was removed
            // to keep this demo as simple as possible.
            // The method of determining cost was designed in order
            // to exploit small and coplanar regions for
            // effective polygon reduction.
            // Is is possible to add some checks here to see if "folds"
            // would be generated.  i.e. normal of a remaining face gets
            // flipped.  I never seemed to run into this problem and
            // therefore never added code to detect this case.
            int   i;
            float edgelength = (v.m_position - u.m_position).magnitude;
            float curvature  = 0;

            // find the "sides" triangles that are on the edge uv
            List <WedgeTriangle> sides = u.GetSharedTrianglesWithWedge(v);

            if (sides.Count < 2) //wedge u cannot be collapsed on v because this edge is non manifold (i.e does not have 2 adjacent triangle)
            {
                return(-1);      //return a negative/invalid cost
            }
            // use the triangle facing most away from the sides
            // to determine our curvature term
            for (i = 0; i < u.AdjacentTriangles.Count; i++)
            {
                Vector3 n1      = u.AdjacentTriangles[i].m_normal;
                float   mincurv = 1; // curve for face i and closer side to it
                for (int j = 0; j < sides.Count; j++)
                {
                    // use dot product of face normals
                    Vector3 n2 = sides[j].m_normal;
                    float   dotprod;
                    if (n1 == n2)
                    {
                        dotprod = 1;
                    }
                    else
                    {
                        dotprod = n1.x * n2.x + n1.y * n2.y + n1.z * n2.z;
                    }
                    mincurv = Mathf.Min(mincurv, (1 - dotprod) / 2.0f);
                }
                curvature = Mathf.Max(curvature, mincurv);
            }



            //Debug.Log("cost between " + u.ID + " and " + v.ID + " is " + edgelength * curvature);

            // the more coplanar the lower the curvature term
            return(edgelength * curvature);
        }
Beispiel #8
0
 public void Delete()
 {
     for (int i = 0; i < 3; i++)
     {
         Wedge wedge = m_wedges[i];
         if (wedge != null)
         {
             wedge.RemoveAdjacentTriangle(this);
         }
     }
 }
Beispiel #9
0
        public void ReplaceWedge(Wedge vOld, Wedge vNew)
        {
            for (int i = 0; i != 3; i++)
            {
                if (vOld == m_wedges[i])
                {
                    m_wedges[i] = vNew;
                }
            }

            vNew.AddAdjacentTriangle(this);
            ComputeNormal();
        }
Beispiel #10
0
        /**
         * Core function of the algorithm
         * **/
        private void ProgressiveMesh(ModelData data, out int[] map, out int[] permutation)
        {
            PrepareMeshData(data.Verts, data.Tris);

            ComputeAllEdgeCollapseCosts();

            //for (int i = 0; i != m_wedges.Count; i++)
            //{
            //    Wedge mn = m_wedges[i];
            //    if (mn.m_collapse != null)
            //        Debug.Log("wedge " + mn.ID + " costs " + mn.m_cost + " to collapse on " + mn.m_collapse.ID);
            //}

            map         = new int[m_wedges.Count];
            permutation = new int[m_wedges.Count];

            // reduce the object down to nothing
            while (m_wedges.Count > 0)
            {
                // get the next vertex to collapse
                Wedge mn = MinimumCostEdge();
                // keep track of this vertex, i.e. the collapse ordering
                permutation[mn.ID] = m_wedges.Count - 1;
                // keep track of vertex to which we collapse to
                map[m_wedges.Count - 1] = (mn.m_collapse != null) ? mn.m_collapse.ID : -1;
                // Collapse this edge
                Collapse(mn, mn.m_collapse);

                //if (mn.m_collapse != null)
                //    Debug.Log("Wedge " + mn.ID + " collapses on wedge " + mn.m_collapse.ID + " with cost " + mn.m_cost);

                //first time we encounter a wedge that cannot collapse, we store here the count of remaining wedges including the one we just try to collapse
                if (mn.m_collapse == null && m_minRendereWedgesCount <= 3)
                {
                    m_minRendereWedgesCount = m_wedges.Count + 1;
                }
            }

            // reorder the map list based on the collapse ordering
            for (int i = 0; i < map.Length; i++)
            {
                //map[i] = (map[i] == -1) ? 0 : permutation[map[i]];
                if (map[i] >= 0)
                {
                    map[i] = permutation[map[i]];
                }
            }
        }
Beispiel #11
0
        /**
         * Build neighbourly relations between vertices and wedges using the triangles of the model
         **/
        private void BuildNeighbourlyRelations(List <Wedge> wedges, Vertex[] vertices, List <int> tris)
        {
            for (int i = 0; i != tris.Count; i += 3)
            {
                Vertex v0 = vertices[tris[i]];
                Vertex v1 = vertices[tris[i + 1]];
                Vertex v2 = vertices[tris[i + 2]];

                Triangle triangle = new Triangle(v0, v1, v2);
                //m_triangles.Add(triangle);

                //Set this triangle as an adjacent triangle for every vertex
                //v0.AddAdjacentTriangle(triangle);
                //v1.AddAdjacentTriangle(triangle);
                //v2.AddAdjacentTriangle(triangle);

                //for each triangle vertex, set the 2 opposite points as neighbors
                //v0.AddNeighbor(v1);
                //v0.AddNeighbor(v2);
                //v1.AddNeighbor(v0);
                //v1.AddNeighbor(v2);
                //v2.AddNeighbor(v0);
                //v2.AddNeighbor(v1);

                Wedge w0 = GetWedgeHoldingVertex(wedges, v0);
                Wedge w1 = GetWedgeHoldingVertex(wedges, v1);
                Wedge w2 = GetWedgeHoldingVertex(wedges, v2);

                w0.AddNeighbor(w1);
                w0.AddNeighbor(w2);
                w1.AddNeighbor(w0);
                w1.AddNeighbor(w2);
                w2.AddNeighbor(w0);
                w2.AddNeighbor(w1);

                WedgeTriangle wedgeTriangle = new WedgeTriangle(w0, w1, w2);
                wedgeTriangle.m_mappedVertexTriangle = triangle; //map here the vertex triangle to the wedge triangle

                if (wedges == m_initialWedges)                   //populate the m_originalTriangles using the m_initialWedges list only
                {
                    m_originalTriangles.Add(wedgeTriangle);
                }

                w0.AddAdjacentTriangle(wedgeTriangle);
                w1.AddAdjacentTriangle(wedgeTriangle);
                w2.AddAdjacentTriangle(wedgeTriangle);
            }
        }
Beispiel #12
0
        /**
         * Collapse the wedge u onto the wedge v
         * **/
        private void Collapse(Wedge u, Wedge v)
        {
            //Collapse the edge uv by moving wedge u onto v
            // Actually remove tris on uv, then update tris that
            // have u to have v, and then remove u.
            if (v == null)
            {
                // u is a vertex all by itself so just delete it
                u.Delete();
                m_wedges.Remove(u);
                return;
            }

            // delete triangles on edge uv:
            List <WedgeTriangle> uvSharedTriangles = u.GetSharedTrianglesWithWedge(v);

            for (int i = 0; i != uvSharedTriangles.Count; i++)
            {
                uvSharedTriangles[i].Delete();
            }

            // update remaining triangles to have v instead of u
            for (int i = 0; i != u.AdjacentTriangles.Count; i++)
            {
                u.AdjacentTriangles[i].ReplaceWedge(u, v);
            }

            //add u neighbors to v and add v as a new neighbor of u neighbors
            for (int i = 0; i != u.Neighbors.Count; i++)
            {
                if (u.Neighbors[i] != v)
                {
                    v.AddNeighbor(u.Neighbors[i]);
                    u.Neighbors[i].AddNeighbor(v);
                }
            }

            u.Delete();
            m_wedges.Remove(u);

            // recompute the edge collapse costs for neighboring vertices
            for (int i = 0; i < u.Neighbors.Count; i++)
            {
                ComputeEdgeCostAtWedge(u.Neighbors[i]);
            }
        }
Beispiel #13
0
        /**
         * Tell if this vertex can collapse on one of the vertices of the parameter 'wedge'
         * Return the Vertex on which this vertex can collapse on
         **/
        public Vertex FindVertexToCollapseOn(Wedge wedge)
        {
            if (wedge == null)
            {
                return(null);
            }

            for (int i = 0; i != wedge.Vertices.Count; i++)
            {
                if (wedge.Vertices[i].ShareTriangleWithVertex(this))
                {
                    return(wedge.Vertices[i]);
                }
            }

            return(null);
        }
Beispiel #14
0
        /**
         * Return the triangles shared by two wedges.
         **/
        public List <WedgeTriangle> GetSharedTrianglesWithWedge(Wedge wedge)
        {
            List <WedgeTriangle> sharedTriangles = new List <WedgeTriangle>();

            for (int i = 0; i < m_adjacentTriangles.Count; i++)
            {
                for (int j = 0; j != wedge.m_adjacentTriangles.Count; j++)
                {
                    if (m_adjacentTriangles[i] == wedge.m_adjacentTriangles[j])
                    {
                        sharedTriangles.Add(m_adjacentTriangles[i]);
                    }
                }
            }

            return(sharedTriangles);
        }
        /**
         * Core function of the algorithm
         * **/
        private void ProgressiveMesh(ModelData data, out int[] map, out int[] permutation)
        {
            PrepareMeshData(data);

            ComputeAllEdgeCollapseCosts();

            //int[] mapArray = new int[m_wedges.Count]; // allocate space
            //int[] permutationArray = new int[m_wedges.Count]; // allocate space
            map         = new int[m_wedges.Count];
            permutation = new int[m_wedges.Count];

            // reduce the object down to nothing
            while (m_wedges.Count > 0)
            {
                // get the next vertex to collapse
                Wedge mn = MinimumCostEdge();

                //if (mn.m_collapse != null)
                //    Debug.Log("collapsing wedge " + mn.ID + " on wedge " + mn.m_collapse.ID + " with cost " + mn.m_cost);

                // keep track of this vertex, i.e. the collapse ordering
                permutation[mn.ID] = m_wedges.Count - 1;
                // keep track of vertex to which we collapse to
                map[m_wedges.Count - 1] = (mn.m_collapse != null) ? mn.m_collapse.ID : -1;
                // Collapse this edge
                Collapse(mn, mn.m_collapse);
                //copy mapped, displaced and deleted vertices to the wedge that will remain alive
                Wedge persistentWedge = WedgeForID(m_initialWedges, mn.ID);
                persistentWedge.m_collapsedVertices = mn.m_collapsedVertices;
                persistentWedge.m_displacedVertices = mn.m_displacedVertices;
                persistentWedge.m_deletedVertices   = mn.m_deletedVertices;
            }

            // reorder the map list based on the collapse ordering
            for (int i = 0; i < map.Length; i++)
            {
                //map[i] = (map[i] == -1) ? 0 : permutation[map[i]];
                if (map[i] >= 0)
                {
                    map[i] = permutation[map[i]];
                }
            }
        }
        private void BuildWedges(List <Wedge> wedges, ModelData data)
        {
            Vertex[] vertices = new Vertex[data.Verts.Length];

            //First sort vertices into wedges
            for (int i = 0; i != data.Verts.Length; i++)
            {
                Vertex vertex = new Vertex(data.Verts[i], i);
                if (data.Colors != null && data.Colors.Length > 0)
                {
                    vertex.m_color = data.Colors[i];
                }
                if (data.UVs != null && data.UVs.Length > 0)
                {
                    vertex.m_uv = data.UVs[i];
                }
                vertices[i] = vertex;

                Wedge wedge = WedgeForPosition(wedges, data.Verts[i]);
                if (wedge != null)
                {
                    wedge.AddVertex(vertex);
                }
                else
                {
                    wedge = new Wedge(data.Verts[i], wedges.Count);
                    wedge.AddVertex(vertex);
                    wedges.Add(wedge);
                }
            }

            //Build neighbourly relations between vertices and wedges using the triangles of the model
            BuildNeighbourlyRelations(wedges, vertices, data.Tris);

            //Determine which triangles are adjacent to each wedge
            for (int i = 0; i != m_wedges.Count; i++)
            {
                m_wedges[i].InvalidateAdjacentTriangles();
            }
        }
Beispiel #17
0
 /**
  * Compute the cost to collapse a specific edge to one of its neighbors (the one with the least cost is chosen)
  * **/
 private void ComputeEdgeCostAtWedge(Wedge w)
 {
     // compute the edge collapse cost for all edges that start
     // from vertex v.  Since we are only interested in reducing
     // the object by selecting the min cost edge at each step, we
     // only cache the cost of the least cost edge at this vertex
     // (in member variable collapse) as well as the value of the
     // cost (in member variable objdist).
     if (w.Neighbors.Count == 0)
     {
         // v doesn't have neighbors so it costs nothing to collapse
         w.m_collapse = null;
         w.m_cost     = 0;
         return;
     }
     w.m_cost     = 1000000;
     w.m_collapse = null;
     // search all neighboring edges for "least cost" edge
     for (int i = 0; i < w.Neighbors.Count; i++)
     {
         float dist;
         dist = ComputeEdgeCollapseCost(w, w.Neighbors[i]);
         if (dist < 0) //non-manifold edge
         {
             w.m_collapse = null;
             w.m_cost     = 0;
         }
         else
         {
             if (dist < w.m_cost)
             {
                 w.m_collapse = w.Neighbors[i]; // candidate for edge collapse
                 w.m_cost     = dist;           // cost of the collapse
             }
         }
     }
 }
Beispiel #18
0
        /**
         * Return the vertex with the 'least cost' to collapse
         * **/
        private Wedge MinimumCostEdge()
        {
            // Find the edge that when collapsed will affect model the least.
            // This funtion actually returns a Vertex, the second vertex
            // of the edge (collapse candidate) is stored in the vertex data.
            // Serious optimization opportunity here: this function currently
            // does a sequential search through an unsorted list :-(
            // Our algorithm could be O(n*lg(n)) instead of O(n*n)
            Wedge mn      = null;
            float minCost = float.MaxValue;

            for (int i = 0; i < m_wedges.Count; i++)
            {
                if (m_wedges[i].m_collapse == null)
                {
                    continue;
                }

                if (m_wedges[i].m_cost == 0) //zero cost, take the first wedge we encounter
                {
                    return(m_wedges[i]);
                }

                if (m_wedges[i].m_cost < minCost)
                {
                    mn      = m_wedges[i];
                    minCost = m_wedges[i].m_cost;
                }
            }

            if (mn == null) //we spent all wedges that collapse, only wedges with null collapse remain so return the first one
            {
                mn = m_wedges[0];
            }

            return(mn);
        }
Beispiel #19
0
 public bool HasNeighbor(Wedge neighbor)
 {
     return(m_neighbors.Contains(neighbor));
 }
        /**
         * Return a list of vertices and indices where player has specified a maximum count of vertices for the initial model
         **/
        public void CutMeshPolygons(out ModelData cutData, int maxWedges, bool bStopWatch = false)
        {
            //no work to do here
            if (maxWedges >= m_initialWedges.Count)
            {
                cutData = m_data;
                return;
            }

            //list of vertices deleted during the process of collapsing
            //System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            //sw.Start();

            //int counter = 0;
            //while (counter < 1E04)
            //{
            //   FindDeletedVertices(maxWedges);
            //    counter++;
            //}
            //sw.Stop();
            //Debug.Log("V1 took " + sw.ElapsedMilliseconds + " ms");

            //sw = new System.Diagnostics.Stopwatch();
            //sw.Start();

            //counter = 0;
            //while (counter < 1E04)
            //{
            //    FindDeletedVertices2(maxWedges);
            //    counter++;
            //}
            //sw.Stop();
            //Debug.Log("V2 took " + sw.ElapsedMilliseconds + " ms");

            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            if (bStopWatch)
            {
                sw = new System.Diagnostics.Stopwatch();
                sw.Start();
            }

            //List<int> deletedVertices = FindDeletedVertices(maxWedges);
            int[] deletedVertices = FindDeletedVertices(maxWedges);

            //list of vertices displaced during the process of collapsing
            List <DisplacedVertex> displacedVertices = FindDisplacedVertices(maxWedges);

            //map vertices that have collapsed
            List <CollapsedVertex> collapsedVertices = MapVertices(maxWedges);

            //copy IDs of collapsed and deleted vertices into an array and sort it by ascending order
            int[] dismissedVerticesIDs = new int[collapsedVertices.Count + deletedVertices.Length];
            for (int i = 0; i != collapsedVertices.Count; i++)
            {
                dismissedVerticesIDs[i] = collapsedVertices[i].m_initialIndex;
            }

            for (int i = collapsedVertices.Count; i != dismissedVerticesIDs.Length; i++)
            {
                dismissedVerticesIDs[i] = deletedVertices[i - collapsedVertices.Count];
            }

            if (dismissedVerticesIDs.Length > 1)
            {
                System.Array.Sort(dismissedVerticesIDs);
            }

            if (bStopWatch)
            {
                sw.Stop();
                Debug.Log("STEP1 took " + sw.ElapsedMilliseconds + " ms");
            }

            if (bStopWatch)
            {
                sw = new System.Diagnostics.Stopwatch();
                sw.Start();
            }

            //Traverse wedges (untouched and collapsed ones) and fill in the vertices array by shifting one vertex according to the previous sorted array
            Vertex[] cutVertices = new Vertex[m_data.Verts.Length];
            int      maxID       = -1;

            for (int i = 0; i != m_initialWedges.Count; i++)
            {
                Wedge wedge = m_initialWedges[i];
                for (int j = 0; j != wedge.Vertices.Count; j++)
                {
                    Vertex vertex = wedge.Vertices[j];

                    //create a copy of this vertex to maintain intact the original one
                    Vertex copiedVertex = new Vertex();
                    copiedVertex.m_position = vertex.m_position;
                    copiedVertex.ID         = vertex.ID;
                    copiedVertex.m_color    = vertex.m_color;
                    copiedVertex.m_uv       = vertex.m_uv;

                    //test if the vertex collapsed or has been deleted
                    bool bDismissVertex = false;
                    for (int p = 0; p != dismissedVerticesIDs.Length; p++)
                    {
                        if (dismissedVerticesIDs[p] == copiedVertex.ID)
                        {
                            bDismissVertex = true;
                        }
                    }

                    if (!bDismissVertex)
                    {
                        //test if it has been displaced and update its position accordingly
                        for (int p = 0; p != displacedVertices.Count; p++)
                        {
                            if (displacedVertices[p].m_index == copiedVertex.ID)
                            {
                                copiedVertex.m_position = displacedVertices[p].m_targetPosition;
                                break;
                            }
                        }

                        //compute the new id of this vertex and populate the new vertex array
                        int id = GetShiftedID(dismissedVerticesIDs, copiedVertex.ID);
                        if (id > maxID)
                        {
                            maxID = id;
                        }
                        if (cutVertices[id] == null)
                        {
                            cutVertices[id] = copiedVertex;
                        }
                    }
                }
            }

            //use the maximum vertex index to crop the array
            System.Array.Resize(ref cutVertices, maxID + 1);

            if (bStopWatch)
            {
                sw.Stop();
                Debug.Log("STEP2 took " + sw.ElapsedMilliseconds + " ms");
            }

            //now build the triangle list
            List <int> triangles = new List <int>();

            for (int i = 0; i != m_data.Tris.Length; i += 3)
            {
                int p0 = m_data.Tris[i];
                int p1 = m_data.Tris[i + 1];
                int p2 = m_data.Tris[i + 2];

                //first check if all triangle vertices still exist
                bool bDismissTriangle = false;
                for (int p = 0; p != deletedVertices.Length; p++)
                {
                    if (p0 == deletedVertices[p] || p1 == deletedVertices[p] || p2 == deletedVertices[p])
                    {
                        bDismissTriangle = true;
                        break;
                    }
                }

                if (bDismissTriangle)
                {
                    continue;
                }

                //if this triangle is valid, find the correct ID for each vertex
                p0 = GetShiftedID(dismissedVerticesIDs, GetCollapseIDForID(collapsedVertices, p0));
                p1 = GetShiftedID(dismissedVerticesIDs, GetCollapseIDForID(collapsedVertices, p1));
                p2 = GetShiftedID(dismissedVerticesIDs, GetCollapseIDForID(collapsedVertices, p2));

                //one-dimensional (flat) triangle, dismiss it
                if (p0 == p1 || p1 == p2 || p2 == p0)
                {
                    continue;
                }

                //accumulate triangle normal for each vertex
                Triangle triangle = new Triangle(cutVertices[p0], cutVertices[p1], cutVertices[p2]);
                //cutVertices[p0].AccumulateNormalFromTriangle(triangle.m_normal);
                //cutVertices[p1].AccumulateNormalFromTriangle(triangle.m_normal);
                //cutVertices[p2].AccumulateNormalFromTriangle(triangle.m_normal);

                triangles.Add(p0);
                triangles.Add(p1);
                triangles.Add(p2);
            }

            //extract data from the Vertex array
            Vector3[] outputVertices = new Vector3[cutVertices.Length];
            //Vector3[] outputNormals = new Vector3[cutVertices.Length];
            Color[]   outputColors = (m_data.Colors != null) ? new Color[cutVertices.Length] : null;
            Vector2[] outputUVs    = (m_data.UVs != null) ? new Vector2[cutVertices.Length] : null;
            for (int i = 0; i != outputVertices.Length; i++)
            {
                //vertices
                outputVertices[i] = cutVertices[i].m_position;
                //normals
                //outputNormals[i] = cutVertices[i].GetAccumulationNormal();
                //colors
                if (outputColors != null)
                {
                    outputColors[i] = cutVertices[i].m_color;
                }
                //uv
                if (outputUVs != null)
                {
                    outputUVs[i] = cutVertices[i].m_uv;
                }
            }

            cutData = new ModelData(outputVertices, triangles.ToArray());
            //cutData.Normals = outputNormals;
            cutData.Colors = outputColors;
            cutData.UVs    = outputUVs;
        }
        /**
         * Map the vertices of all the wedges that have been cut down beyond the maxWedges limit
         **/
        private List <CollapsedVertex> MapVertices(int maxWedges)
        {
            List <CollapsedVertex> collapsedVertices = new List <CollapsedVertex>();

            for (int i = m_initialWedges.Count - 1; i != maxWedges - 1; i--)
            {
                Wedge         wedge             = m_initialWedges[i];
                List <Vertex> wedgeVerticesCopy = new List <Vertex>(wedge.Vertices);

                for (int v = 0; v != wedgeVerticesCopy.Count; v++)
                {
                    Wedge collapseWedge = wedge; //reset the wedge to the actual wedge holding this vertex

                    CollapsedVertex collapsedVertex = new CollapsedVertex(-1, -1);
                    Vertex          vertex          = wedgeVerticesCopy[v];
                    collapsedVertex.m_initialIndex = vertex.ID;

                    int stopIndex = 0;
                    while (collapseWedge.ID >= maxWedges && stopIndex < 100)
                    {
                        if (collapseWedge.m_collapse == null)
                        {
                            break;
                        }

                        //Vertex collapseVertex = vertex.FindVertexToCollapseOn(collapseWedge.m_collapse);
                        Vertex collapseVertex = collapseWedge.MapVertex(vertex);

                        if (collapseVertex != null)
                        {
                            vertex = collapseVertex;
                            collapsedVertex.m_collapsedIndex = collapseVertex.ID;
                        }

                        //collapseWedge = collapseWedge.m_collapse;
                        //int nextWedgeIndex = m_collapseMap[collapseWedge.ID];
                        //if (nextWedgeIndex >= 0)
                        //    collapseWedge = m_initialWedges[m_collapseMap[collapseWedge.ID]];
                        //else
                        //    break;

                        int nextWedgeIndex = m_collapseMap[collapseWedge.ID];
                        if (nextWedgeIndex == 0)
                        {
                            break;
                        }
                        else
                        {
                            collapseWedge = collapseWedge.m_collapse;
                        }


                        //if (collapseWedge != null)
                        //{
                        //    //set the vertex position as the position of the last wedge it collapsed to or been moved to
                        //    collapsedVertex.m_position = collapseWedge.m_position;
                        //}

                        stopIndex++;
                    }
                    if (stopIndex >= 99)
                    {
                        Debug.Log("stopIndex:" + stopIndex);
                    }

                    if (collapsedVertex.m_collapsedIndex >= 0)
                    {
                        collapsedVertices.Add(collapsedVertex);
                    }
                }
            }

            return(collapsedVertices);
        }
        /**
         * Collapse the wedge u onto the wedge v
         * **/
        private void Collapse(Wedge u, Wedge v)
        {
            // Collapse the edge uv by moving vertex u onto v
            // Actually remove tris on uv, then update tris that
            // have u to have v, and then remove u.
            if (v == null)
            {
                // u is a vertex all by itself so just delete it
                u.Delete();
                m_wedges.Remove(u);
                return;
            }

            //Find vertices that will collapse or be displaced
            for (int i = 0; i != u.Vertices.Count; i++)
            {
                Vertex vertex         = u.Vertices[i];
                Vertex collapseVertex = vertex.FindVertexToCollapseOn(v); //the vertex it will collapse on if it exists

                if (collapseVertex != null)
                {
                    u.m_collapsedVertices.Add(vertex.ID, collapseVertex.ID); //no exception will be thrown as unique IDs are inserted into that dictionary

                    //CollapsedVertex collapsedVertex = new CollapsedVertex(vertex.ID, collapseVertex.ID);

                    //u.m_collapsedVertices.Add(collapsedVertex);
                }
                else
                {
                    DisplacedVertex displacedVertex = new DisplacedVertex();
                    displacedVertex.m_index          = vertex.ID;
                    displacedVertex.m_targetPosition = v.m_position;

                    u.m_displacedVertices.Add(displacedVertex);
                }
            }

            //delete triangles on edge[u - v]
            List <Triangle> sharedTriangles = u.GetSharedTrianglesWithWedge(v);

            for (int i = 0; i != sharedTriangles.Count; i++)
            {
                //delete the triangle
                sharedTriangles[i].Delete();

                for (int j = 0; j != sharedTriangles[i].Vertices.Length; j++)
                {
                    Vertex vertex = sharedTriangles[i].Vertices[j];

                    if (!u.HasVertex(vertex) && !v.HasVertex(vertex)) //the third wedge that is not u or v holds this vertex
                    {
                        if (vertex.AdjacentTriangles.Count == 0)      //vertex is isolated, remove it
                        {
                            //find the wedge and remove the vertex from its internal list
                            GetWedgeHoldingVertex(m_wedges, vertex).RemoveVertex(vertex);
                            //add the vertex ID to the list of vertices deleted during the operation of collapsing u onto v
                            u.m_deletedVertices.Add(vertex.ID);
                        }
                    }
                }
            }

            //perform the actual collapse
            u.CollapseOnWedge(v);

            //add u neighbors to v and add v as a new neighbor of u neighbors
            for (int i = 0; i != u.Neighbors.Count; i++)
            {
                if (u.Neighbors[i] != v)
                {
                    v.AddNeighbor(u.Neighbors[i]);
                    u.Neighbors[i].AddNeighbor(v);
                }
            }

            //neighbors of wedge u are likely to have lost one triangle through one of their vertex so invalidate them
            for (int i = 0; i != u.Neighbors.Count; i++)
            {
                u.Neighbors[i].InvalidateAdjacentTriangles();
            }

            //delete the wedge and remove it from global list
            u.Delete();
            m_wedges.Remove(u);

            // recompute the edge collapse costs for neighboring wedges
            for (int i = 0; i < u.Neighbors.Count; i++)
            {
                ComputeEdgeCostAtWedge(u.Neighbors[i]);
            }
        }
Beispiel #23
0
 public bool HasWedge(Wedge w)
 {
     return(m_wedges[0] == w || m_wedges[1] == w || m_wedges[2] == w);
 }