/** * 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); } }
public void AddNeighbor(Wedge neighbor) { if (!HasNeighbor(neighbor)) { m_neighbors.Add(neighbor); } }
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(); //} }
public void RemoveNeighbor(Wedge neighbor) { if (HasNeighbor(neighbor)) { m_neighbors.Remove(neighbor); } }
} // 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(); }
/** * 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); } }
/** * 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); }
public void Delete() { for (int i = 0; i < 3; i++) { Wedge wedge = m_wedges[i]; if (wedge != null) { wedge.RemoveAdjacentTriangle(this); } } }
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(); }
/** * 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]]; } } }
/** * 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); } }
/** * 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]); } }
/** * 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); }
/** * 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(); } }
/** * 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 } } } }
/** * 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); }
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]); } }
public bool HasWedge(Wedge w) { return(m_wedges[0] == w || m_wedges[1] == w || m_wedges[2] == w); }