Berechnung Mesh normals
-
Eine Normale steht senkrecht auf der Oberflaeche und wird per Kreuzprodukt aus zwei Vektoren (zb die Kanten eines Dreiecks) berechnet.
Soll die Oberflaeche rund erscheinen werden pro Eckpunkt die Normalen aller angrenzenden Dreiecke (den Indizes der Traingle-List zu entnehmen) gemittelt.
Uebersteigt der Winkel zwischen zwei benachbarten Dreiecken einen gewissen Grad, so soll diese Kante ggf sichtbar bleiben und Dreiecke jenseits dieser Kante fliessen nicht mit in die Mittelung ein.
Fuer gewoehnlich entscheidet der Artist beim Modellieren wo Shading-Kanten hingehoeren und weisst geeignete Normalen/Gruppierungen zu.
-
wenn ich ein Dreieck ABC A(1,1,1) B(0,1,1) C(1,0,1) habe wären die normalen:
für A = CxA oder BxA
für B = AxC
für C = AxBstimmt das?
-
-
[...] stimmt das?
Die Kanten eines Dreiecks (A,B,C) verlaufen von A nach B, B nach C und C nach A (bzw andersrum).
Der Vektor "A" hingegen verlaeuft von (0,0,0) nach A.
-
(Vector(A) - Vector(B)) X (Vector(A)-Vecotr(C)) = Normalvektor
X -> Kreuzprodukt
Korrigiert mich wenn ich mich irre
-
dieser code hier hat bei mir funktioniert (c# mit direct3d)
private void ComputeNormals() { for (int i = 0; i < vertices.Length; i++) vertices[i].Normal = new Vector3(0f, 0f, 0f); for (int i = 0; i < indices.Length / 3; i++) { Vector3 normal = Vector3.Cross( vertices[indices[i * 3]].Position - vertices[indices[i * 3 + 2]].Position, vertices[indices[i * 3]].Position - vertices[indices[i * 3 + 1]].Position); vertices[indices[i * 3]].Normal += normal; vertices[indices[i * 3 + 1]].Normal += normal; vertices[indices[i * 3 + 2]].Normal += normal; } for (int i = 0; i < vertices.Length; i++) vertices[i].Normal.Normalize(); }
vertices ist ein VertexBuffer und indices ein IndexBuffer
-
jule37 schrieb:
for (int i = 0; i < vertices.Length; i++)
vertices[i].Normal = new Vector3(0f, 0f, 0f);den schritt verstehe ich nicht ganz wozu füllst du die normal erst mit 0 Vektoren auf?
-
wozu füllst du die normal erst mit 0 Vektoren auf?
Damit kein Bloedsinn drinsteht.
-
Die Facenormalen sollten noch mit dem Winkel zwischen den beiden Kanten (die zum berechnen verwendet wurden) gewichtet werden um sowas zu vermeiden: L-Shape.
-
in manchen faellen macht das das resultat "richtiger" in manchen wiederrum "falscher", sollte man also nur bedingt einsetzen.
edit: oh, ich glaube da hab ich gerade bloedsinn geschrieben
-
jule37 schrieb:
dieser code hier hat bei mir funktioniert (c# mit direct3d)
private void ComputeNormals() { for (int i = 0; i < vertices.Length; i++) vertices[i].Normal = new Vector3(0f, 0f, 0f); for (int i = 0; i < indices.Length / 3; i++) { Vector3 normal = Vector3.Cross( vertices[indices[i * 3]].Position - vertices[indices[i * 3 + 2]].Position, vertices[indices[i * 3]].Position - vertices[indices[i * 3 + 1]].Position); vertices[indices[i * 3]].Normal += normal; vertices[indices[i * 3 + 1]].Normal += normal; vertices[indices[i * 3 + 2]].Normal += normal; } for (int i = 0; i < vertices.Length; i++) vertices[i].Normal.Normalize(); }
vertices ist ein VertexBuffer und indices ein IndexBuffer
Hab dann doch noch eine Frage. Wer hätte das gedacht
Warum fügst du ein und die selbe normale 3 mal ein?
David_pb@ Wie mache ich das den?
-
Warum fügst du ein und die selbe normale 3 mal ein?
Weil ein Dreieck an drei Punkten anliegt.
Darf ich mal fragen in welcher Klasse Du bist?
-
Das mir schon klar, nur müsste man die normale dann nicht noch verschieben?
Schule ja schon lang vorbei
-
müsste man die normale dann nicht noch verschieben?
Die Normale gibt nur die Richtung an, kannste hinstellen wo Du willst.
Schule ja schon lang vorbei
Dann solltest Du das Thema Vektorrechnung dringend mal auffrischen.
-
Joe schrieb:
David_pb@ Wie mache ich das den?
Naja, den Winkel zwischen beiden Kanten berechnen und die errechnete Normale damit skalieren.