Theoretisch könntest du die Normalen natürlich auch einfach selbst berechnen, mit dem Kreuzprodukt, wie oben von Firoball vorgeschlagen. Wenn du das machst und die Werte beim Rendern übergibst, kriegst du aber Flat Shading raus, und das finden wir ja alle nicht mehr so schön. Darum nimmt man dann meist den Durchschnitt der umliegenden Faces.
Als ich damals meine Engine mit OpenGL geschrieben hatte, hatte ich für jeden Vertex einen einzelnen "Normalenwert" übergeben können. Wenn ich den von Wings3D benutzt habe, war das auch ein sehr schönes Gourad-shading, das hat mir die eigene Berechnung erspart (obwohl ich das auch mal versucht hatte).
Wie dem auch sei! So sieht das ja beispielsweise aus:
Code:
vn -0.57735027 -0.57735027 0.57735027
vn -0.57735027 0.57735027 0.57735027
vn 0.57735027 0.57735027 0.57735027
vn 0.57735027 -0.57735027 0.57735027
...
Wird ja alles in einer langen Liste gespeichert. Im Face-teil sind dann ja pro Vertex, dass zu dem Face gehört, mehrere Zahlen gespeichert, die sich dann auf die Position des Vertex in der Liste, die Position der Texturkoordinaten in der Liste und die Position der Normale in der Liste bestimmt.
Der jeweils dritte Wert bei "f", also bei
Code:
f 1//2 4//4 3//3 2//1
die jeweils letzte Zahl (2,4,3,1) ist der Wert der Normalen in der Liste. D.h. der erste Vertex von diesem Face hat die Normale -0.57735027 -0.57735027 0.57735027 (siehe Liste oben), der zweite Vertex dieses Face die Normale vn 0.57735027 -0.57735027 0.57735027, usw.
Wenn dein Modellprogramm dir das nicht exportiert, oder wenn du das ganze selber machen willst, musst du die Normalen wohl oder übel selber berechnen:
Machen wir das erstmal für die einzelnen Faces (wird dann ohne "ausgleichen" ein Flat Shading). Für unser Beispielface oben ist das schonmal schwierig, denn das ist ja ein Quad - und vier Punkte müssen nicht unbedingt in der Ebene liegen. Um das ganze erstmal einfahc zu halten, führen wir die bedingung ein, dass das Model nur aus Dreiecken besteht (kann fast jeder Editor mit einer Option wie "Triangulate"). Beispiel einer Pyramide, das ist die v-Liste:
Code:
v -1.00000000 -1.00000000 1.00000000
v 1.00000000 -1.00000000 1.00000000
v -1.00000000 -1.00000000 -1.00000000
v 1.00000000 -1.00000000 -1.00000000
v 0.0000000e+0 1.00000000 0.0000000e+0
und dass hier ist die f-Liste:
Code:
f 1//1 2//2 5//5
f 1//1 4//4 2//2
f 2//2 4//4 5//5
f 3//3 4//4 1//1
f 5//5 3//3 1//1
f 5//5 4//4 3//3
(Natürlich gibts hier schon Normalenwerte - aber die ignorieren wir mal und berechnen unsere eigenen).
Für das erste Face haben wir die folgenden drei Vertices:
Code:
v -1.00000000 -1.00000000 1.00000000
v 1.00000000 -1.00000000 1.00000000
v 0.0000000e+0 1.00000000 0.0000000e+0
Um nun die Normale des zugehörigen Face zu erhalten, rechnen wir erstmal die beiden Richtungsvektoren aus, die wir erhalten, wenn wir von "Vertex 1" zu "Vertex 2" bzw. "Vertex 3" gehen. Das macht:
u = v2 - v1 = 1-(-1) -1-(-1) 1-1 = 2 0 0
v = v3 - v1 = 0-(-1) 1-(-1) 0-1 = 1 2 -1
Und nun kommt das Kreuzprodukt zum Tragen - das Kreuzprodukt gibt uns den Vektor, der senkrecht auf diesen beiden steht. Im dreidimensionalen sind das natürlich beliebig viele, die aber alle parallel (bzw. antiparallel zueinander sind).
Wir erhalten einen davon, indem wir u x v rechnen, nach der Formel oben:
u2*v3 - u3*v2 = 0*(-1) - 0*2 = 0
u3*v1 - u1*v3 = 0*1 - 2*(-1) = 2
u1*v2 - u2*v1 = 2*2 - 0*1 = 4
Die Normale dieses Face lautet also 0|2|4 - die knönen wir dann zb. für die Beleuchtung angeben. Wenn du diese Berechnung jetzt für jedes Face durchführst, kannst du das ganze schön schattieren. Wenn du dann für jeden Vertex den Durchschnitt aller umliegenden Faces berechnest und dass als Normale übergibst (kann man - zumindest bei OpenGL - für jeden Vertex machen), dann wirkt das ganze viel sanfter und "runder". Natürlich sind das eine ganze Menge Berechnungen, musst du dir überlegen, ob du das nicht lieber alles einmal berechnest und dann speicherst und später nur darauf zugreifst.
Mit etwas Pech ist die Normale aber jetzt gerade "falschrum" - dann müssen wir sie invertieren, indem wir jeden Wert mit -1 multiplizieren, dann wäre der Vektor also 0|-2|-4.
Um einen Normalenvektor der Länge 1 zu erhalten, müssen wir ihn normalisieren, d.h. durch seine Länge teilen. Die Länge kriegst du mit:
|x| = sqrt(x1²+x2²+x3²)
hier also
sqrt(0+4+16) = sqrt(20) = 2*sqrt(5) ~ 4,472135
teilen wir die Werte dadurch, erhalten wir:
0|-0,4472135955|-0,89442738
(ungefähr, natürlich).
Und dass wäre dann der Normalenvektor dieses Face!
So. Ich hoffe, dass hat dir geholfen.
EDIT: Ist aber alles schon 'ne Weile her. Wenn ich hier Stuss erzähle, bitte ich, mich zu korrigieren.