public Vector3 GetMergedPosition_Optimal() { Matrix4x4 Q = SimplifyHelper.AddMatrices(Q1, Q2);
Matrix4x4 A = new Matrix4x4(); A.SetRow(0, new Vector4(Q.m00, Q.m01, Q.m02, 0)); A.SetRow(1, new Vector4(Q.m10, Q.m11, Q.m12, 0)); A.SetRow(2, new Vector4(Q.m20, Q.m21, Q.m22, 0));
Vector3 b = new Vector3(-Q.m03, -Q.m13, -Q.m23);
// 求 A 的行列式,判断是否可逆 float det = A.determinant; if (Mathf.Abs(det) > 1e-6f) { Matrix4x4 A_inv = A.inverse; return A_inv.MultiplyPoint3x4(b); } else { return (v1 + v2) * 0.5f; } }
// init vertex's data int vertNum = vertexs.Length; vertex_valid = newbool[vertNum]; Array.Fill(vertex_valid, true);
// init vert links to triangle...... vertex_link_triangle_dict = new Dictionary<int, List<int>>(vertNum); vertex_Q_dict = new Dictionary<int, Matrix4x4>(vertNum); vertex_pair_dict = new Dictionary<int, List<VectorPair>>(vertNum); for (int i = 0; i < vertNum; i++) { vertex_link_triangle_dict[i] = new List<int>(); vertex_pair_dict[i] = new List<VectorPair>(); }
// construct triangle's data int triIdxNum = triangles.Length; if(triIdxNum % 3 != 0) { Debug.Log($"error! not valid triangle num : {triIdxNum}"); return; } int triNum = triIdxNum / 3; triangle_valid = newbool[triNum]; Array.Fill(triangle_valid, true);
// init triangle to vert dict triangle_contains_vert_dict = new Dictionary<int, List<int>>(triNum); triangle_Q_dict = new Dictionary<int, Matrix4x4>(triNum);
for ( int triIdx = 0; triIdx < triNum; triIdx++ ) { int tri_vert_start = triIdx * 3; int v1 = triangles[tri_vert_start]; int v2 = triangles[tri_vert_start + 1]; int v3 = triangles[tri_vert_start + 2];
triangle_contains_vert_dict[triIdx] = new List<int> { v1, v2, v3 };
// init vert Idx to Q dict for (int i = 0; i < vertNum; i++) { List<int> vert_tri_idxs = vertex_link_triangle_dict[i]; Matrix4x4 res = Matrix4x4.zero; foreach (var triIdx in vert_tri_idxs) { res = SimplifyHelper.AddMatrices(res, triangle_Q_dict[triIdx]); } vertex_Q_dict[i] = res; }
// set edge vert's message edgeVertMap = new HashSet<int>(edgeVerts.Count); edgeVert_normals_dict = new Dictionary<int, Vector3>(edgeVerts.Count); for(int i = 0; i < edgeVerts.Count; i++) { edgeVertMap.Add(edgeVerts[i]); }
// init vert pair, add them to heap; qemMinHeap = new QEMMinHeap(); hasAddThisPairMap = new HashSet<string>(); for (int triIdx = 0; triIdx < triNum; triIdx++) { int tri_vert_start = triIdx * 3; int v1 = triangles[tri_vert_start]; int v2 = triangles[tri_vert_start + 1]; int v3 = triangles[tri_vert_start + 2];
publicvoidStartSimplify() { int curCnt = vertCnt; int iterCnt = 0; // 防止无限循环 int maxIter = vertCnt - 1; while(curCnt > targetCnt && iterCnt < maxIter) {
VectorPair pair = qemMinHeap.GetTop();
Vector3 newV = pair.GetMergedPosition(); Matrix4x4 newM = SimplifyHelper.AddMatrices(pair.Q1, pair.Q2); int idx1 = pair.v1Idx; int idx2 = pair.v2Idx; if (!vertex_valid[idx1]) { //Debug.LogError($"vert {idx1} is not valid, 本次 iter cnt :{iterCnt}"); continue; } if (!vertex_valid[idx2]) { //Debug.LogError($"vert {idx2} is not valid, 本次 iter cnt :{iterCnt}"); continue; }
// keep v1, use v1 to storage new V, erase v2 vertexs[idx1] = newV; vertex_valid[idx2] = false;
// update all pair that link to idx2, idx1 int length2 = vertex_pair_dict[idx2].Count; for(int i = length2 - 1; i >= 0; i--) { var idx2_pair = vertex_pair_dict[idx2][i]; if (pair.Equals(idx2_pair) || pair == idx2_pair) { vertex_pair_dict[idx2].RemoveAt(i); continue; }
int length1 = vertex_pair_dict[idx1].Count; for (int i = length1 - 1; i >= 0; i--) { var idx1_pair = vertex_pair_dict[idx1][i]; if (pair.Equals(idx1_pair) || pair == idx1_pair) { vertex_pair_dict[idx1].RemoveAt(i); continue; }
// add all v2's vertex pair to v1 foreach (var idx2_pair in vertex_pair_dict[idx2]) { if (idx2_pair.v1Idx != idx1 && idx2_pair.v2Idx != idx1) { Debug.LogError($"不应该出现的情况,idx1 没有设置正确 * 2 :{idx2_pair.v1Idx},{idx2_pair.v2Idx},{idx1},{idx2},iterCnt: {iterCnt}"); //continue; } vertex_pair_dict[idx1].Add(idx2_pair); }
// update all triangle that link to idx2, replace them to idx1 int commonTriCnt = 0; foreach (var triIdx in vertex_link_triangle_dict[idx2]) { if (!triangle_valid[triIdx]) { continue; }
if (IsCommonTriangle(idx1, idx2, triIdx)) { triangle_valid[triIdx] = false; commonTriCnt++; }
UpdateTriangleVert(idx2, idx1, triIdx); }
// 把 idx2 的所有相邻三角形,移交给 idx1 顶点 foreach (var triIdx in vertex_link_triangle_dict[idx2]) { if (!triangle_valid[triIdx]) { continue; }
if (!vertex_link_triangle_dict[idx1].Contains(triIdx)) { vertex_link_triangle_dict[idx1].Add(triIdx); } }
curCnt--;
iterCnt++; if (iterCnt >= maxIter) { Debug.LogError("simplify end because iterCnt has reach its limit"); } }
}
privateboolIsCommonTriangle(int idx1, int idx2, int triIdx) {
// triangle that use this pair as common egde, set them not valid int tri_vert_start = triIdx * 3; int tri_v1 = triangles[tri_vert_start]; int tri_v2 = triangles[tri_vert_start + 1]; int tri_v3 = triangles[tri_vert_start + 2];
// delete vertex not valid int vertNum = vertexs.Length; List<Vector3> newVerts = new List<Vector3>(); int curOffset = 0; for (int i = 0; i < vertNum; i++) { if (!vertex_valid[i]) { curOffset++; continue; }
int newIdx = i - curOffset; // old idx is bigger,so no conflict foreach (var triIdx in vertex_link_triangle_dict[i]) { UpdateTriangleVert(i, newIdx, triIdx); }
newVerts.Add(vertexs[i]); }
// delete un valid tris List<int> newTriangles = new List<int>(); int triIdxNum = triangles.Length; int triNum = triIdxNum / 3; for (int triIdx = 0; triIdx < triNum; triIdx++) { if (!triangle_valid[triIdx]) { continue; }
int tri_vert_start = triIdx * 3; int v1 = triangles[tri_vert_start]; int v2 = triangles[tri_vert_start + 1]; int v3 = triangles[tri_vert_start + 2];