/// <summary> /// Entfernt den obersten VertexSplit von dem VertexSplit Stack und führt ihn /// durch. /// </summary> /// <returns> /// true, wenn ein VertexSplit aus dem Stack entnommen wurde und durchgeführt /// wurde; andernfalls false, d.h. der Stack war schon leer. /// </returns> /// <remarks> /// Das Durchführen einer VertexSplit Operation hat immer das Pushen seiner /// Umkehroperation auf den Contraction Stack zur Folge. /// </remarks> public bool PerformVertexSplit() { if (Splits.Count == 0) { return(false); } if (incidentFaces == null) { incidentFaces = ComputeIncidentFaces(); // Einmalig alle Vertexnormalen bestimmen. // ComputeNormals(_faces); } var split = Splits.Pop(); // 1. Vertex s wird an neue Position verschoben. Vertices[split.S] = new Vertex() { Position = split.SPosition }; // 2. Vertex t wird neu zur Mesh hinzugefügt. Vertices[NumberOfVertices] = new Vertex() { Position = split.TPosition }; uint t = (uint)NumberOfVertices; // 3. Umkehroperation des VertexSplits auf Contraction Stack pushen. Contractions.Push(new Contraction() { S = split.S, Position = Vertices[split.S].Position, faceOffset = NumberOfFaces, VertexSplit = split }); NumberOfVertices++; // 4. Alle Facetten von s, die ursprünglich t "gehört" haben, auf t zurückbiegen. var facesOfS = incidentFaces[split.S]; var facesOfT = new HashSet <Face>(); incidentFaces.Add(t, facesOfT); var removeFromS = new HashSet <Face>(); foreach (var f in facesOfS) { var _c = IsOriginalFaceOfT(t, f, split); if (_c < 0) { continue; } f[_c] = t; facesOfT.Add(f); removeFromS.Add(f); } foreach (var r in removeFromS) { facesOfS.Remove(r); } // 5. Etwaige gemeinsame Facetten von s und t der Mesh neu hinzufügen. foreach (var f in split.Faces) { if (!f.Indices.Contains(split.S)) { continue; } var newFace = new Face(f.Indices, FlatFaces, NumberOfFaces * 3); NumberOfFaces++; for (int c = 0; c < 3; c++) { incidentFaces[newFace[c]].Add(newFace); } } // Normalen aller betroffenen Vertices neuberechnen. ComputeNormals(incidentFaces[split.S].Union(incidentFaces[t])); return(true); }