Normalenberechnung bei GL_QUAD_STRIP



  • Ich muss nun doch mal etwas Licht in meine OpenGL Szene bekommen und habe soweit alles lichttechnische drin. Das Objektmesh ist nun grau und ich erinnere mich dunkel, dass ich noch die Normalen berechnen muss. Hat da jemand ein Tutorial zu? Ich frage mich gerade, wie man das am effektivsten mit einem GL_QUAD_STRIP macht, ich kenne das bisher nur mit Dreiecken. Vielen Dank!



  • Hm, GL_QUAD_STRIP baut ja Vierecke. Sind deine Vierecke denn planar? Falls dem so ist, kannst du die Normal genauso berechnen wie bei den Dreicken (Kreuzprodukt wenn ich mich recht entsinne 😉 )

    Sollte die 4 Eckpunkte allerdings nicht in einer Ebene liegen, kanns kompliziert werden. Das Viereck kann ja entarten und somit ist die Normale nicht wirklich eindeutig. Ich würde dir empfehlen, dass du Dreiecke nutzt, wenn du die Möglichkeit hast. Die meisten Algorithmen sind dafür ausgelegt und du kommst nicht in die Gefahr, eine "nicht-ebene" Fläche zu erhalten 🙂

    Grüße
    Neron



  • Hmmmm ne, sind nicht alle planar. Dann muss ich also mal Quellcode suchen, wie man die Normale mit 3 Punkten berechnet...



  • Hm? Ne Normale mit 3 Punkten berechnen? Klingt seltsam, aber vielleicht kann ich ja etwas helfen.

    Also, in OpenGL gibst du ja nicht die Normale für ein ganzes Dreieck an, sondern nur für den Punkt, den du jeweils zeichnest. Dabei kannst du natürlich für ein Dreieck die Normale speichern und diese beim Zeichnen dann für alle 3 Punkte angeben. Ein benachbartes Dreieck hätte zwar gemeinsame Punkte, für die du dann aber andere Normalen angeben must. Würde dann ungefähr so aussehen:

    // berechne Normale für Dreieck 0
    ...
    // zeichne alle Punkte von Dreieck 0 (inklusive Normale)
    glNormal3f( n.x, n.y, n.z );
    glVertex3f( vertex00.x, vertex00.y, vertex00.z );
    glNormal3f( n.x, n.y, n.z );
    glVertex3f( vertex01.x, vertex01.y, vertex01.z );
    glNormal3f( n.x, n.y, n.z );
    glVertex3f( vertex02.x, vertex02.y, vertex02.z );
    
    // berechne Normale für Dreieck 1
    ...
    // zeichne alle Punkte von Dreieck 1 (inklusive Normale)
    glNormal3f( n.x, n.y, n.z );
    glVertex3f( vertex10.x, vertex10.y, vertex10.z );
    glNormal3f( n.x, n.y, n.z );
    glVertex3f( vertex11.x, vertex11.y, vertex11.z );
    glNormal3f( n.x, n.y, n.z );
    glVertex3f( vertex12.x, vertex12.y, vertex12.z );
    
    usw.
    

    Allerdings ist diese Methode nicht sonderlich genau, da es für's gesamte Dreieck nur 1 Normale gibt (Flat Shading). Besser wäre da ein Gouraud Shading. Dabei berechnest du für jeden Eckpunkt die "echte" Normale und interpolierst zwischen den Eckpunkten (Ich glaube, das ist unter OpenGL aktivierbar) Etwa so:

    // berechne Normale für Dreieck 0 - Eckpunkt 0
    ...
    // zeichne Punkt 0 inklusive Normale
    glNormal3f( n0.x, n0.y, n0.z );
    glVertex3f( vertex00.x, vertex00.y, vertex00.z );
    // berechne Normale für Dreieck 0 - Eckpunkt 1
    ...
    // zeichne Punkt 1 inklusive Normale
    glNormal3f( n1.x, n1.y, n1.z );
    glVertex3f( vertex01.x, vertex01.y, vertex01.z );
    // berechne Normale für Dreieck 0 - Eckpunkt 2
    ...
    // zeichne Punkt 2 inklusive Normale
    glNormal3f( n2.x, n2.y, n2.z );
    glVertex3f( vertex02.x, vertex02.y, vertex02.z );
    
    usw
    

    Der Vorteil dabei ist dann, dass du das auch für Vierecksflächen nutzen kannst, da OpenGL automatisch zwischen den Eckpunkten interpoliert. Am besten wäre also, wenn du für jeden Eckpunkt deines Netzes noch die entsprechende Normale speicherst und die beim Zeichnen dann immer davor setzt.

    Die Berechnung der Normale eines Punktes ist auch nicht sehr schwer. Ich meine, es ist die Summe der Normalen aller Dreiecke, die diesen Punkt enthalten. Dann einfach noch normalisieren und schon hast ne schicke Normale. Allerdings beachten, dass alle Normalen in die gleiche Richtung zeigen. Sollten sie ja eigentlich, aber kann ja doch mal passieren, dass man einen Vektor vertauscht 😉

    Hoffe das hilft
    Grüße
    Neron



  • Danke für die ausführliche Antwort! Ich probiere gerade, das ganze so zu machen, wie ich es vor 2 Jahren in Delphi schonmal gemacht habe. Das sah so aus:

    http://www.delphigl.com/forum/viewtopic.php?p=23317

    Weiter unten ist der Quelltext dazu. Gouraud ist nicht nötig für meine Software, Flatshading wird schon reichen.



  • Besser ist auf jeden Fall ein Dreiecksnetz wegen den Entartungen. Zerlege deine Quads doch einfach in Dreiecke und berechne die Normale:

    n=(ab)×(ac)\vec{n} = (\vec{a} - \vec{b}) \times (\vec{a}-\vec{c})

    Wobei a,b,c die Dreieckspunkte sind.

    Achte auf die Orientierung (alle Normalen müssen von der Fläche weg zeigen) sonst bekommst du schwarze Dreiecke.

    @Neron
    Für eine Dreiecksnormale brauchst du den Befehl

    glNormal3f(n.x,n.y,n.z);
    

    nur einmal

    gruß megaweber



  • megaweber schrieb:

    @Neron
    Für eine Dreiecksnormale brauchst du den Befehl

    glNormal3f(n.x,n.y,n.z);
    

    nur einmal

    Mist - hab ich später noch gemerkt, aber dachte mir vielleicht sieht's ja keiner 😉

    @JPSelter: soweit ich das sehe, ist der Delphi-Code zur Normalenberechnung in Ordnung. Wie megaweber schon gesagt hat, wichtig ist halt darauf zu achten, dass die Normalen die richtige Orientierung haben 🙂

    Grüße
    Neron



  • Du kannst ja jedem Eckpunkt 'ne Normale geben. Also einfach für jeden Punkt und seine zwei Nachbarn rechnen. Ist doch ganz einfach! f'`8k

    Gruß, TGGC (\-/ returns)



  • GL_QUAD_STRIP ... Flatshading

    eigentlich widerspruechlich:
    das konzept der strips geht davon aus, dass zwei benachbarte polygone an ihrer gemeinsamen kante auch gemeinsame vertex-parameter haben.
    bei flat-shading haben aber alle vertices von polygon A eine normale und alle vertices von polygon B eine andere.


Anmelden zum Antworten