Ich habe eine Klasse, die eine 3D-Form basierend auf Eingaben aus dem aufrufenden Code generiert. Bei den Eingaben handelt es sich um Dinge wie Länge, Tiefe, Bogen usw. Mein Code generiert die Geometrie perfekt, es treten jedoch Probleme bei der Berechnung der Oberflächennormalen auf. Wenn beleuchtet, hat meine Form eine sehr bizarre Färbung / Textur aufgrund der falschen Oberflächennormalen, die berechnet werden. Nach all meinen Nachforschungen glaube ich, dass meine Mathematik korrekt ist. Es scheint, dass etwas mit meiner Technik oder Methode nicht stimmt.
Wie kann man auf hoher Ebene die Oberflächennormalen für eine generierte Form programmatisch berechnen? Ich verwende Swift / SceneKit unter iOS für meinen Code, aber eine generische Antwort ist in Ordnung.
Ich habe zwei Arrays, die meine Form darstellen. Eine ist eine Reihe von 3D-Punkten, die die Eckpunkte darstellen, aus denen die Form besteht. Das andere Array ist eine Liste der Indizes des ersten Arrays, die die Eckpunkte in Dreiecke abbilden. Ich muss diese Daten nehmen und ein drittes Array generieren, das eine Reihe von Oberflächennormalen ist, die die Beleuchtung der Form unterstützen. (siehe SCNGeometrySourceSemanticNormal
in SceneKit` )
Die Liste der Eckpunkte und Indizes ist abhängig von den Eingaben in die Klasse immer unterschiedlich, sodass ich die Oberflächennormalen nicht vorberechnen oder hart codieren kann.
Antworten:
Sie wollen einfach keine glatten Ergebnisse. Während die kommentierte Methode von Nathan Reed: "Berechne jeden Scheitelpunkt so, dass er normal ist, summiere sie und normalisiere die Summe", funktioniert sie im Allgemeinen manchmal auf spektakuläre Weise. Aber das ist hier nicht wichtig, wir können diese Methode anwenden, indem wir eine Ablehnungsklausel hinzufügen.
In diesem Fall möchten Sie einfach, dass bestimmte Teile nicht gegen bestimmte andere Teile geglättet werden. Sie möchten selektive harte Kanten. So ist beispielsweise die flache Oberseite und die flache Unterseite von dem Dreiecksstreifen an der Seite getrennt, ebenso wie jede flache Fläche.
Bild 1 : Das gewünschte Ergebnis.
Tatsächlich möchten Sie nur die Scheitelpunkte des gekrümmten Bereichs mitteln. Alle anderen können die Normalen verwenden, die sie nur aus ihrem Dreieck erhalten. Sie sollten sich das Netz also besser als 9 separate Regionen vorstellen, die ohne die anderen behandelt werden.
Bild 2 : Bild zeigt die Maschenstruktur und die Normalen.
Sie können dies sicherlich automatisch ableiten, indem Sie Normalen, die außerhalb eines bestimmten Winkels liegen, nicht von den Normalen der primären Scheitelpunkte einbeziehen. Pseudocode:
Das funktioniert, aber Sie können all dies beim Erstellen einfach vermeiden, da Sie verstehen, dass separate Ebenen unterschiedlich funktionieren. Es müssen also nur die gekrümmten Seiten in normaler Richtung zusammengeführt werden. Und tatsächlich können Sie sie direkt aus der zugrunde liegenden mathematischen Form berechnen.
quelle
Ich sehe hauptsächlich drei Möglichkeiten, Normalen für eine generierte Form zu berechnen.
Analytische Normalen
In einigen Fällen verfügen Sie über genügend Informationen zur Oberfläche, um die Normalen zu generieren. Zum Beispiel ist die Normale eines Punktes auf einer Kugel trivial zu berechnen. Einfach ausgedrückt, wenn Sie die Ableitung der Funktion kennen, kennen Sie auch das Normale.
Wenn Ihr Fall so eng ist, dass Sie analytische Normalen verwenden können, erzielen Sie wahrscheinlich das beste Ergebnis in Bezug auf die Genauigkeit. Die Technik ist jedoch nicht sehr gut skalierbar: Wenn Sie auch Fälle behandeln müssen, in denen Sie keine analytischen Normalen verwenden können, ist es möglicherweise einfacher, die Technik, die den allgemeinen Fall behandelt, beizubehalten und den analytischen Fall insgesamt zu löschen.
Vertexnormalen
Das Kreuzprodukt zweier Vektoren ergibt einen Vektor senkrecht zu der Ebene, zu der sie gehören. Die Normalität eines Dreiecks zu erhalten ist also ganz einfach:
Darüber hinaus ist im obigen Beispiel die Länge des Querprodukts proportional zur Fläche innerhalb von abc . So kann die geglättete Normale an einem Scheitelpunkt, der von mehreren Dreiecken geteilt wird, berechnet werden, indem die Kreuzprodukte summiert und als letzter Schritt normalisiert werden, wodurch jedes Dreieck mit seiner Fläche gewichtet wird.
Wenn Sie mit Quads arbeiten, gibt es einen schönen Trick können Sie verwenden: für ein Quad - abcd , Gebrauch
crossProduct(c - a, d - b)
und es wird behandeln schön Fälle , in denen das Quad in der Tat ist ein Dreieck.Iñigo quilez schrieb ein paar kurze Artikel zum Thema: Kluge Normalisierung eines Netzes sowie Normal und Fläche von n-seitigen Polygonen .
Normalen aus partiellen Ableitungen
Aus den partiellen Ableitungen können im Fragment-Shader Normalen berechnet werden. Die Mathematik dahinter ist dieselbe, außer dass diesmal im Bildschirmbereich gearbeitet wird. Dieser Artikel von Angelo Pesce beschreibt die Technik: Normale ohne Normale .
quelle