/// <summary> /// Erzeugt und speichert einen VertexSplit Eintrag für das angegebene Paar. /// </summary> /// <param name="p"> /// Das Paar für welches ein VertexSplit Eintrag erstellt werden soll. /// </param> void AddSplitRecord(Pair p) { contractionIndices.Push(p.Vertex2); var split = new VertexSplit() { S = p.Vertex1, SPosition = vertices[p.Vertex1], TPosition = vertices[p.Vertex2] }; foreach (var f in incidentFaces[p.Vertex2]) { // -1 wird später durch eigentlichen Index ersetzt, wenn dieser bekannt // ist. split.Faces.Add(new Triangle( f.Indices[0] == p.Vertex2 ? -1 : f.Indices[0], f.Indices[1] == p.Vertex2 ? -1 : f.Indices[1], f.Indices[2] == p.Vertex2 ? -1 : f.Indices[2])); } splits.Push(split); }
private void Contract(int targetTriangles, IProgressListener listener = null) { SelectValidPairs(); if (listener != null) { listener.OnStarted("Compacting"); } int totalTriangles = m_Faces.Count - targetTriangles; int currentTriangle = 0; while (m_Faces.Count > targetTriangles) { if (listener != null) { listener.OnStep(currentTriangle, totalTriangles); } ++currentTriangle; double minError = (double)int.MaxValue; //KeyValuePair<VertexPair, double> min; VertexPair minPair = new VertexPair() { First = 0, Second = 0 }; foreach (KeyValuePair<VertexPair, double> e in m_Errors) { if (e.Value < minError) { minError = e.Value; minPair = e.Key; } } Vector3 error; ComputeError(minPair.First, minPair.Second, out error); #if false VertexSplit split = new VertexSplit(); //var fv split.First.Position = m_Vertices[minPair.First].Position; split.Second.Position = m_Vertices[minPair.Second].Position; split.Target.Position = error; m_Splits.Add(split); #endif var vertex = m_Vertices[minPair.First]; vertex.Position = error; m_Quadrics[minPair.First] = m_Quadrics[minPair.First] + m_Quadrics[minPair.Second]; for (int i = m_Faces.Count - 1; i != 0; ) { var face = m_Faces[i]; for (int j = 0; j < 3; ++j) { if (face[j] == minPair.Second) { if (face[0] == minPair.First || face[1] == minPair.First || face[2] == minPair.First) { m_Faces.Remove(face); } else { face[j] = minPair.First; } --i; break; } else if (j == 2) { --i; } } } m_Vertices.Remove(minPair.Second); KeyValuePair<VertexPair, double> pair; #if false for (int iter = m_Errors.Count - 1; iter != 0; ) { pair = m_Errors.ElementAt(iter); if (pair.Key.First == minPair.Second && pair.Key.Second != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(iter).Key); m_Errors.Add( new VertexPair() { First = Math.Min(minPair.First, pair.Key.Second), Second = Math.Max(minPair.First, pair.Key.Second) }, 0.0); --iter; } else if (pair.Key.Second == minPair.Second && pair.Key.First != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(iter).Key); m_Errors.Add( new VertexPair() { First = Math.Min(minPair.First, pair.Key.First), Second = Math.Max(minPair.First, pair.Key.First) }, 0.0); --iter; } else { --iter; } } #else for (int it = 0; it < m_Errors.Count; ++it) { pair = m_Errors.ElementAt(it); if (pair.Key.First == minPair.Second && pair.Key.Second != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(it).Key); var key = new VertexPair() { First = Math.Min(minPair.First, pair.Key.Second), Second = Math.Max(minPair.First, pair.Key.Second) }; if (!m_Errors.ContainsKey(key)) { m_Errors.Add( key, 0.0); } } else if (pair.Key.Second == minPair.Second && pair.Key.First != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(it).Key); var key = new VertexPair() { First = Math.Min(minPair.First, pair.Key.First), Second = Math.Max(minPair.First, pair.Key.First) }; if (!m_Errors.ContainsKey(key)) { m_Errors.Add( key, 0.0); } } } #endif m_Errors.Remove(minPair); for (int it = 0; it < m_Errors.Count; ++it) { var key = m_Errors.ElementAt(it).Key; if (key.First == minPair.First) { m_Errors[key] = ComputeError(minPair.First, key.Second); } if (key.Second == minPair.First) { m_Errors[key] = ComputeError(minPair.First, key.First); } } /*foreach (var e in m_Errors) { var p = e.Key; if (p.First == minPair.First) { m_Errors[p] = ComputeError(minPair.First, p.Second); } if (p.Second == minPair.First) { m_Errors[p] = ComputeError(minPair.First, p.First); } }*/ } if (listener != null) { listener.OnComplete("Compacting"); } }
private void Contract(int targetTriangles, IProgressListener listener = null) { SelectValidPairs(); if (listener != null) { listener.OnStarted("Compacting"); } int totalTriangles = m_Faces.Count - targetTriangles; int currentTriangle = 0; while (m_Faces.Count > targetTriangles) { if (listener != null) { listener.OnStep(currentTriangle, totalTriangles); } ++currentTriangle; double minError = (double)int.MaxValue; //KeyValuePair<VertexPair, double> min; VertexPair minPair = new VertexPair() { First = 0, Second = 0 }; foreach (KeyValuePair <VertexPair, double> e in m_Errors) { if (e.Value < minError) { minError = e.Value; minPair = e.Key; } } Vector3 error; ComputeError(minPair.First, minPair.Second, out error); #if false VertexSplit split = new VertexSplit(); //var fv split.First.Position = m_Vertices[minPair.First].Position; split.Second.Position = m_Vertices[minPair.Second].Position; split.Target.Position = error; m_Splits.Add(split); #endif var vertex = m_Vertices[minPair.First]; vertex.Position = error; m_Quadrics[minPair.First] = m_Quadrics[minPair.First] + m_Quadrics[minPair.Second]; for (int i = m_Faces.Count - 1; i != 0;) { var face = m_Faces[i]; for (int j = 0; j < 3; ++j) { if (face[j] == minPair.Second) { if (face[0] == minPair.First || face[1] == minPair.First || face[2] == minPair.First) { m_Faces.Remove(face); } else { face[j] = minPair.First; } --i; break; } else if (j == 2) { --i; } } } m_Vertices.Remove(minPair.Second); KeyValuePair <VertexPair, double> pair; #if false for (int iter = m_Errors.Count - 1; iter != 0;) { pair = m_Errors.ElementAt(iter); if (pair.Key.First == minPair.Second && pair.Key.Second != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(iter).Key); m_Errors.Add( new VertexPair() { First = Math.Min(minPair.First, pair.Key.Second), Second = Math.Max(minPair.First, pair.Key.Second) }, 0.0); --iter; } else if (pair.Key.Second == minPair.Second && pair.Key.First != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(iter).Key); m_Errors.Add( new VertexPair() { First = Math.Min(minPair.First, pair.Key.First), Second = Math.Max(minPair.First, pair.Key.First) }, 0.0); --iter; } else { --iter; } } #else for (int it = 0; it < m_Errors.Count; ++it) { pair = m_Errors.ElementAt(it); if (pair.Key.First == minPair.Second && pair.Key.Second != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(it).Key); var key = new VertexPair() { First = Math.Min(minPair.First, pair.Key.Second), Second = Math.Max(minPair.First, pair.Key.Second) }; if (!m_Errors.ContainsKey(key)) { m_Errors.Add( key, 0.0); } } else if (pair.Key.Second == minPair.Second && pair.Key.First != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(it).Key); var key = new VertexPair() { First = Math.Min(minPair.First, pair.Key.First), Second = Math.Max(minPair.First, pair.Key.First) }; if (!m_Errors.ContainsKey(key)) { m_Errors.Add( key, 0.0); } } } #endif m_Errors.Remove(minPair); for (int it = 0; it < m_Errors.Count; ++it) { var key = m_Errors.ElementAt(it).Key; if (key.First == minPair.First) { m_Errors[key] = ComputeError(minPair.First, key.Second); } if (key.Second == minPair.First) { m_Errors[key] = ComputeError(minPair.First, key.First); } } /*foreach (var e in m_Errors) * { * var p = e.Key; * if (p.First == minPair.First) * { * m_Errors[p] = ComputeError(minPair.First, p.Second); * } * * if (p.Second == minPair.First) * { * m_Errors[p] = ComputeError(minPair.First, p.First); * } * }*/ } if (listener != null) { listener.OnComplete("Compacting"); } }