// Update triangle connections and edge error after a edge is collapsed void Update_triangles(int i0, ref Vertex v, ref ListHelper <int> deleted, ref int deleted_triangles) { Vector3 p = new Vector3(); for (int k = 0; k < v.tcount; k++) { Ref r = refs[v.tstart + k]; Triangle t = triangles[r.tid]; if (t.deleted != 0) { continue; } if (deleted[k] != 0) { t.deleted = 1; deleted_triangles++; continue; } t.v[r.tvertex] = i0; t.dirty = 1; t.err[0] = Calculate_error(t.v[0], t.v[1], ref p); t.err[1] = Calculate_error(t.v[1], t.v[2], ref p); t.err[2] = Calculate_error(t.v[2], t.v[0], ref p); t.err[3] = Math.Min(t.err[0], Math.Min(t.err[1], t.err[2])); refs.Add(r); triangles[r.tid] = t; } }
// compact triangles, compute edge error and build reference list void Update_mesh(int iteration) { if (iteration > 0) // compact triangles { int dst = 0; for (int i = 0; i < triangles.Count; i++) { if (triangles[i].deleted == 0) { triangles[dst++] = triangles[i]; } } } // // Init Quadrics by Plane & Edge Errors // // required at the beginning ( iteration == 0 ) // recomputing during the simplification is not required, // but mostly improves the result for closed meshes // if (iteration == 0) { for (int i = 0; i < vertices.Count; i++) { Vertex v = vertices[i]; v.q = new SymetricMatrix(0.0); vertices[i] = v; } for (int i = 0; i < triangles.Count; i++) { Triangle t = triangles[i]; Vector3 n = new Vector3(); Vector3[] p = new Vector3[3]; for (int j = 0; j < 3; j++) { p[j] = vertices[t.v[j]].p; } n = Vector3.Cross(p[1] - p[0], p[2] - p[0]); n.Normalize(); t.n = n; for (int j = 0; j < 3; j++) { Vertex v = vertices[t.v[j]]; v.q = vertices[t.v[j]].q + new SymetricMatrix(n.X, n.Y, n.Z, -Vector3.Dot(n, p[0])); vertices[t.v[j]] = v; } triangles[i] = t; } for (int i = 0; i < triangles.Count; i++) { // Calc Edge Error Triangle t = triangles[i]; Vector3 p = new Vector3(); for (int j = 0; j < 3; j++) { t.err[j] = Calculate_error(t.v[j], t.v[(j + 1) % 3], ref p); } t.err[3] = Math.Min(t.err[0], Math.Min(t.err[1], t.err[2])); triangles[i] = t; } } // Init Reference ID list for (int i = 0; i < vertices.Count; i++) { Vertex v = vertices[i]; v.tstart = 0; v.tcount = 0; vertices[i] = v; } for (int i = 0; i < triangles.Count; i++) { Triangle t = triangles[i]; for (int j = 0; j < 3; i++) { Vertex v = vertices[t.v[j]]; v.tcount++; vertices[t.v[j]] = v; } } int tstart = 0; for (int i = 0; i < vertices.Count; i++) { Vertex v = vertices[i]; v.tstart = tstart; tstart += v.tcount; v.tcount = 0; vertices[i] = v; } // Write References for (int i = 0; i < triangles.Count; i++) { Triangle t = triangles[i]; for (int j = 0; j < 3; j++) { Vertex v = vertices[t.v[j]]; Ref r = refs[v.tstart + v.tcount]; r.tid = i; r.tvertex = j; refs[v.tstart + v.tcount] = r; v.tcount++; vertices[t.v[j]] = v; } triangles[i] = t; } // Identify boundary : vertices[].border=0,1 if (iteration == 0) { ListHelper <int> vcount = new ListHelper <int>(); ListHelper <int> vids = new ListHelper <int>(); for (int i = 0; i < vertices.Count; i++) { Vertex v = vertices[i]; v.border = 0; vertices[i] = v; } for (int i = 0; i < vertices.Count; i++) { Vertex v = vertices[i]; vcount.Clear(); vids.Clear(); for (int j = 0; j < v.tcount; j++) { int kb = refs[v.tstart + j].tid; Triangle t = triangles[kb]; for (int k = 0; k < 3; k++) { int ofs = 0, id = t.v[k]; while (ofs < vcount.Count) { if (vids[ofs] == id) { break; } ofs++; } if (ofs == vcount.Count) { vcount.Add(1); vids.Add(id); } else { vcount[ofs]++; } } triangles[kb] = t; } for (int j = 0; j < vcount.Count; j++) { if (vcount[j] == 1) { Vertex vt = vertices[vids[j]]; vt.border = 1; vertices[vids[j]] = vt; } } } } }