/// <summary> /// 塌陷一个点 /// </summary> /// <param name="mesh"></param> /// <param name="rv"></param> protected static void Collapse(LODMesh mesh, RepeatedVertex rv, bool reCompute = false) { RepeatedVertex to = rv.collapsedTo; // 删除点 rv.deleteFlag = true; // 删除边 LODEdge edge = new LODEdge(rv.index, rv.collapsedTo.index); LODEdge target = mesh.edges.Find((item) => { return(edge.Equals(item)); }); target.deleteFlag = true; // 删除面 List <int> remains = new List <int>(); List <int> deletedFaces = GetEdgeShareFaces(mesh, rv.index, to.index, remains); foreach (int del in deletedFaces) { mesh.faces[del].deleteFlag = true; } // 更新面 foreach (int remain in remains) { // 顶点更新 mesh.faces[remain].Replace(mesh, rv.index, to.index); // uv更新 // todo } // 更新临点 if (reCompute) { List <RepeatedVertex> neighbors = new List <RepeatedVertex>(); RefreshNeighbor(mesh, rv); } }
/// <summary> /// 塌陷处理 /// </summary> /// <param name="mesh"></param> protected static void CollapseMesh(LODMesh mesh) { RepeatedVertex rv = mesh.Pop(); while (rv != null) { Collapse(mesh, rv); rv = mesh.Pop(); } }
/// <summary> /// 此处一次只会删一个点 /// </summary> public void Delete(RepeatedVertex rv) { int split = rv.index; foreach (int n in rv.neighborVertices) { vertices[n].neighborVertices.Remove(split); } vertices.RemoveAt(split); }
/// <summary> /// 初始化所有边塌陷代价值 /// </summary> /// <param name="mesh"></param> protected static void InitializeAllEdgeCost(LODMesh mesh) { int cnt = mesh.vertices.Count; for (int i = 0; i < cnt; ++i) { RepeatedVertex v = mesh.vertices[i]; v.collapsedTo = null; EdgeCostAtVertex(mesh, v); mesh.AddHeap(v); } }
protected static void RefreshNeighbor(LODMesh mesh, RepeatedVertex rv) { List <int> neighbors = rv.neighborVertices; foreach (int n in neighbors) { if (mesh.vertices[n].deleteFlag) { continue; } EdgeCostAtVertex(mesh, mesh.vertices[n]); } }
/// <summary> /// 判断 点是否是 一条边界边的点 /// </summary> protected static bool IsBorder(LODMesh mesh, RepeatedVertex v) { foreach (int nei in v.neighborVertices) { LODEdge tmp = new LODEdge(v.index, nei); LODEdge edge = mesh.edges.Find((item) => { return(tmp.Equals(item)); }); if (edge != null) { if (edge.shareCount == 1) { return(true); } } } return(false); }
protected static void EdgeCostAtVertex(LODMesh mesh, RepeatedVertex v) { bool isBorder = IsBorder(mesh, v); for (int j = 0; j < v.neighborVertices.Count; ++j) { int ij = v.neighborVertices[j]; int shareCount = 0; float edgeCurvatureCost = EdgeCurvatureCost(mesh, v.index, ij, ref shareCount); float edgeLen = EdgeLength(mesh, v.index, ij); float cost = edgeCurvatureCost * edgeLen; if (v.collapsedTo == null || cost < v.cost) { v.collapsedTo = mesh.vertices[ij]; v.cost = cost; } } }
protected static List <int> GetEdgeShareFaces(LODMesh mesh, int iIdx, int jIdx, List <int> remain = null) { RepeatedVertex u = mesh.vertices[iIdx]; RepeatedVertex v = mesh.vertices[jIdx]; List <int> totalFaces = u.neighborFaces; List <int> uvFaces = new List <int>(); for (int k = 0; k < totalFaces.Count; ++k) { LODFace face = mesh.faces[totalFaces[k]]; if (face.ContainVertex(jIdx)) { uvFaces.Add(totalFaces[k]); } else { if (remain != null) { remain.Add(totalFaces[k]); // 保留不共享边的面 } } } return(uvFaces); }
protected static LODMesh ParseMesh(Mesh meshIn) { LODMesh lodMesh = new LODMesh(meshIn); List <Vector3> vertices = new List <Vector3>(); meshIn.GetVertices(vertices); List <LODVertex> lodVertices = Convert(vertices); GroupHash <LODVertex> group = new GroupHash <LODVertex>(); group.Objects = lodVertices; List <List <LODVertex> > merged = group.GetResult(); Dictionary <int, RepeatedVertex> originalVertexMapRepeatedIndex = new Dictionary <int, RepeatedVertex>(); for (int i = 0; i < merged.Count; ++i) { RepeatedVertex rpv = new RepeatedVertex(merged[i], i); lodMesh.vertices.Add(rpv); foreach (LODVertex v in merged[i]) { originalVertexMapRepeatedIndex.Add(v.originalIndex, rpv); } } Dictionary <int, LODSubMesh> originalFaceMapSubMeshIndex = new Dictionary <int, LODSubMesh>(); int count = meshIn.subMeshCount; List <int> triangles = new List <int>(); for (int i = 0; i < count; ++i) { LODSubMesh subMesh = new LODSubMesh(i); lodMesh.subMeshes.Add(subMesh); triangles.Clear(); meshIn.GetTriangles(triangles, i); int cnt = triangles.Count; for (int j = 0; j < cnt; j += 3) { int tmp0 = triangles[j]; int tmp1 = triangles[j + 1]; int tmp2 = triangles[j + 2]; int idx0 = originalVertexMapRepeatedIndex[tmp0].index; int idx1 = originalVertexMapRepeatedIndex[tmp1].index; int idx2 = originalVertexMapRepeatedIndex[tmp2].index; int faceIndex = lodMesh.faces.Count; originalFaceMapSubMeshIndex.Add(faceIndex, subMesh); subMesh.faceIndices.Add(faceIndex); lodMesh.faces.Add(new LODFace(lodMesh, lodMesh.subMeshes.Count - 1, idx0, idx1, idx2)); // 绑定临点 originalVertexMapRepeatedIndex[idx0].neighborVertices.Add(idx1); originalVertexMapRepeatedIndex[idx0].neighborVertices.Add(idx2); originalVertexMapRepeatedIndex[idx1].neighborVertices.Add(idx0); originalVertexMapRepeatedIndex[idx1].neighborVertices.Add(idx2); originalVertexMapRepeatedIndex[idx2].neighborVertices.Add(idx0); originalVertexMapRepeatedIndex[idx2].neighborVertices.Add(idx1); // 边 LODEdge e0 = new LODEdge(idx0, idx1); LODEdge e1 = new LODEdge(idx0, idx2); LODEdge e2 = new LODEdge(idx1, idx2); LODEdge ee0 = lodMesh.edges.Find((item) => { return(e0.Equals(item)); }); LODEdge ee1 = lodMesh.edges.Find((item) => { return(e1.Equals(item)); }); LODEdge ee2 = lodMesh.edges.Find((item) => { return(e2.Equals(item)); }); if (ee0 != null) { ee0.Share(); } else { lodMesh.edges.Add(e0); } if (ee1 != null) { ee1.Share(); } else { lodMesh.edges.Add(e1); } if (ee2 != null) { ee2.Share(); } else { lodMesh.edges.Add(e2); } // 临面 originalVertexMapRepeatedIndex[idx0].neighborFaces.Add(faceIndex); originalVertexMapRepeatedIndex[idx1].neighborFaces.Add(faceIndex); originalVertexMapRepeatedIndex[idx2].neighborFaces.Add(faceIndex); } } //for (int i = 0; i < lodMesh.faces.Count - 1; ++i) //{ // // Fill the neighbor faces information in face list // for (int j = i + 1; j < lodMesh.faces.Count; ++j) // { // if (IsNeighbors(lodMesh, i, j)) // { // lodMesh.faces[i].neighboringFaceIndexList.Add(j); // lodMesh.faces[j].neighboringFaceIndexList.Add(i); // } // } //} return(lodMesh); }
/// <summary> /// 判断 点是否是 一条边界边的点 /// </summary> protected static bool IsBorder(LODMesh mesh, int iIdx) { RepeatedVertex v = mesh.vertices[iIdx]; return(IsBorder(mesh, v)); }
public void AddHeap(RepeatedVertex rv) { m_heapCost.Enqueue(rv.index, rv, rv.cost); }