/// <summary> /// Parsed eine VertexSplit Deklaration. /// </summary> /// <param name="l"> /// Die Zeile, die die VertexSplit Deklaration enthält. /// </param> /// <returns> /// Der Vertex-Split Eintrag. /// </returns> /// <exception cref="InvalidOperationException"> /// Die VertexSplit Deklaration ist ungültig. /// </exception> static VertexSplit ParseVertexSplit(string l) { var m = Regex.Match(l, @"^#vsplit\s+(\d+)\s+{(.*)}\s+{(.*)}\s+{(.*)}$"); if (!m.Success) { throw new InvalidOperationException("Invalid vsplit: " + l); } var s = new VertexSplit() { S = int.Parse(m.Groups[1].Value) - 1, SPosition = ParseVector(m.Groups[2].Value), TPosition = ParseVector(m.Groups[3].Value) }; var faceIndices = m.Groups[4].Value; var matches = Regex.Matches(faceIndices, @"\((-?\d+)\s+(-?\d+)\s+(-?\d+)\)"); for (int i = 0; i < matches.Count; i++) { var _m = matches[i]; if (!_m.Success) { throw new InvalidOperationException("Invalid face index entry in vsplit: " + l); } var indices = new[] { int.Parse(_m.Groups[1].Value) - 1, int.Parse(_m.Groups[2].Value) - 1, int.Parse(_m.Groups[3].Value) - 1 }; s.Faces.Add(new Triangle(indices)); } return(s); }
/// <summary> /// Führt eine Vertex-Split Operation auf der Mesh aus. /// </summary> /// <param name="split"> /// Die Vertex-Split Operation, die ausgeführt werden soll. /// </param> /// <param name="incidentFaces"> /// Eine Map die jedem Vertex der Mesh die Menge seiner inzidenten Facetten zuordnet. /// </param> void PerformVertexSplit(VertexSplit split, IDictionary <int, ISet <Triangle> > incidentFaces) { // 1. Vertex s wird an neue Position verschoben. Vertices[split.S].Position = split.SPosition; // 2. Vertex t wird neu zur Mesh hinzugefügt. Vertices.Add(new Vertex() { Position = split.TPosition }); var t = Vertices.Count - 1; // 3. Alle Facetten von s, die ursprünglich t "gehört" haben, auf t zurückbiegen. var facesOfS = incidentFaces[split.S]; var facesOfT = new HashSet <Triangle>(); incidentFaces.Add(t, facesOfT); var removeFromS = new HashSet <Triangle>(); foreach (var f in facesOfS) { var _c = IsOriginalFaceOfT(t, f, split); if (_c < 0) { continue; } f.Indices[_c] = t; facesOfT.Add(f); removeFromS.Add(f); } foreach (var r in removeFromS) { facesOfS.Remove(r); } // 4. 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 Triangle(f.Indices); Faces.Add(newFace); for (int c = 0; c < newFace.Indices.Length; c++) { incidentFaces[newFace.Indices[c]].Add(newFace); } } }
/// <summary> /// Prüft, ob die angegebene Facette ursprünglich dem angegebenen Vertex "gehörte". /// </summary> /// <param name="t"> /// Der Vertex. /// </param> /// <param name="face"> /// Die Facette. /// </param> /// <param name="split"> /// Die zugehörige VertexSplit Instanz. /// </param> /// <returns> /// Der Facettenindex, an dessen Stelle der ursprüngliche Vertex eingetragen war, /// oder -1 falls die Facette nicht ursprünglich dem Vertex "gehörte". /// </returns> /// <remarks> /// Diese Methode könnte schöner sein und sollte eigentlich in 2 Methoden aufgeteilt /// werden: Eine Methode zum Prüfen mit Rückgabewert Bool und eine Methode zum /// Abfragen des Index. Aus Geschwindigkeitsgründen ist dies aber ungünstig. /// </remarks> int IsOriginalFaceOfT(int t, Triangle face, VertexSplit split) { foreach (var f in split.Faces) { var index = -1; var isface = true; for (int i = 0; i < 3; i++) { if (f.Indices[i] == t && face.Indices[i] == split.S) { index = i; } else if (f.Indices[i] != face.Indices[i]) { isface = false; } } if (isface) { return(index); } } return(-1); }