Programmgesteuertes Erzeugen von Scheitelpunktnormalen


10

Ich arbeite mit Kinect Face API. Es bietet eine Reihe von Scheitelpunkten und Indizes für Dreiecke, die gerendert werden sollen, um das Gesichtsbild zu erstellen.

Die Anzahl der Eckpunkte und ihre Reihenfolge im Array sowie die von kinect angegebenen Indizes sind immer konstant.

Die API gibt jedoch keine Informationen zu UV-Daten und Scheitelpunktnormalen.

Die Anwendung erfordert, dass ich die vom Kinect vorgegebene Scheitelpunktreihenfolge einhalte, da sich ihre Positionen im 3D-Raum je nach Gesichtsbewegung ändern, sodass das Generieren von UV- und Normalwerten in einer 3D-Bearbeitungssoftware nicht in Frage kommt.

Ich habe es geschafft, UV zu erzeugen, indem ich die Scheitelpunktpositionen auf eine 2D-Ebene projiziert habe, da es nur sehr wenige Scheitelpunkte auf derselben Ebene gab.

Ich weiß jedoch nicht, wie Scheitelpunktnormalen für das Netz generiert werden sollen. Ohne Scheitelpunktnormalen zeichnet das Gesichtsnetz ohne Tiefe seiner Merkmale aus der Perspektive, obwohl die Silhouette sichtbar ist, wenn die Scheitelpunktpositionen korrekt sind.

Ich verstehe, dass aufgrund des Fehlens von Scheitelpunktnormalen die Beleuchtung nicht richtig funktioniert und daher das blasse, merkwürdige Netz, das es gerade sieht.

Wie generiere ich also Scheitelpunktnormalen, wenn ich nur die Scheitelpunktposition und den Index der Scheitelpunkte habe, um daraus Dreiecke zu machen?


n = (v1 - v0) x (v2 - v0), wobei v0, v1 und v2 die Eckpunkte der fraglichen (Dreiecks-) Fläche sind. Die Bestellung ist wichtig. Normalisieren Sie es, wenn Sie es wirklich brauchen. (und xist Kreuzprodukt)
3Dave

Antworten:


13

Das Berechnen der Normalen aus Scheitelpunktpositionen ist mit dem Vektorkreuzprodukt recht einfach.

Das Kreuzprodukt zweier Vektoren und (notiert oder manchmal ) ist ein Vektor senkrecht zu und mit der Länge , mit der Winkel zwischen und . Die Richtung des Vektors hängt von der Reihenfolge der Multiplikation ab: ist das Gegenteil von (die beiden Richtungen senkrecht zur Ebene).uu × v u v u v | | u × v | | = | | u | | | | v | | s i n ( & thgr ; ) & thgr ; u v u × v v × uvu×vuvuv||u×v||=||u||||v||sin(θ)θuvu×vv×u

Wenn Sie mit dem Cross-Produkt nicht vertraut sind, lade ich Sie ein, darüber zu lesen und sich damit vertraut zu machen. Normalen werden dann einfach erscheinen.

Flache Schattierungsnormalen

Wenn Sie ein Dreieck , ist ein Vektor senkrecht zum Dreieck und mit einer Länge proportional zu seiner Fläche. Da die Normale der Einheitsvektor senkrecht zur Dreiecksebene ist, können Sie die Normalen erhalten mit:A B × A C.ABCAB×AC

N=AB×AC||AB×AC||

Im Code würde dies beispielsweise so aussehen n = normalize(cross(b-a, c-a)). Wenden Sie dies einfach auf alle Ihre Gesichter an und Sie haben Ihre Normalen pro Gesicht.

For each triangle ABC
    n := normalize(cross(B-A, C-A))
    A.n := n
    B.n := n
    C.n := n

Beachten Sie, dass dies voraussetzt, dass Eckpunkte nicht von Dreiecken gemeinsam genutzt werden. Ich bin mit der Kinect-API nicht vertraut. Es ist durchaus möglich, dass sie gemeinsam genutzt werden. In diesem Fall müssten Sie sie duplizieren oder mit der nächsten Lösung fortfahren:

Glatte Schattierungsnormalen

Nach dem Beleuchten mit den oben berechneten Normalen werden Sie feststellen, dass Dreieckskanten sichtbar sind. Wenn dies nicht wünschenswert ist, können Sie stattdessen glatte Normalen berechnen, indem Sie alle Flächen berücksichtigen, die denselben Scheitelpunkt haben.

Die Idee ist, dass, wenn ein gleicher Scheitelpunkt beispielsweise von drei Dreiecken , und geteilt wird , das normale der Durchschnitt von , und . Wenn ein großes Dreieck und ein kleines Dreieck ist, möchten Sie wahrscheinlich, dass stärker von als von .T 2 T 3 N N 1 N 2 N 3 T 1 T 2 N N 1 N 2T1T2T3NN1N2N3T1T2NN1N2

Erinnern Sie sich, wie proportional das Kreuzprodukt zur Fläche ist? Wenn Sie die Kreuzprodukte addieren und dann die Summe normalisieren, ergibt sich genau die gewichtete Summe, die wir wollen. So wird der Algorithmus:

For each vertex
    vertex.n := (0, 0, 0)

For each triangle ABC
    // compute the cross product and add it to each vertex
    p := cross(B-A, C-A)
    A.n += p
    B.n += p
    C.n += p

For each vertex
    vertex.n := normalize(vertex.n)

Diese Technik wird in diesem Artikel von Iñigo Quilez ausführlicher erklärt: clevere Normalisierung eines Netzes .


Weitere Informationen zu Normalen finden Sie auch unter:



Es hat funktioniert Vielen Dank, ein Mann, es hat genau funktioniert, wie ich es wollte
Allahjane


@ Allahjane: Ich bin froh zu hören, dass es gut funktioniert hat. :)
Julien Guertault
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.