Wen ich auf einer Kugel-Oberfläche 2 Punkte habe, wie kann ich den Winkel zwischen den beiden Punkten berechnen ? Dabei ist das Gelenk des Winkels im Zentrum der Kugel. Vom Zentrum aus gesehen haben die Punkte eine bekannte XYZ-Position.
_________________ OpenGL
Zuletzt geändert von mathias am Fr Jun 02, 2017 17:25, insgesamt 1-mal geändert.
Registriert: Mi Aug 14, 2013 21:17 Beiträge: 588
Programmiersprache: C++
Seien P und Q deine beiden Punkte auf der Oberfläche und C der Mittelpunkt der Kugel. Durch Bilden der Differenzen und Teilen durch deren Längen (Normalisieren) kannst du dir zwei Richtungsvektoren der Länge 1 bauen:
Code:
R1 = (P-C) / |P-C|
R2 = (Q-C) / |Q-C|
Das Skalarprodukt zweier Richtungsvektoren der Länge 1 ist der Kosinus des Winkels zwischen ihnen. Also einfach die acos-Funktion drauflos lassen und schon hast du deinen Winkel. In GLSL:
Code:
float winkel(vec3 p,vec3 q,vec3 c){
vec3 r1 =normalize(p-c);
vec3 r2 =normalize(q-c);
returnacos(dot(r1, r2));
}
_________________ So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)
Ich habe gerade noch etwas gefunden, wen mal clamp anstelle acos verwendet, kann man sich die Berechnung mit Pi sparen und wen der Einfallswinkel des Lichtes über 90° ist, ist immer gleich dunkel (schwarz)
Registriert: Mi Aug 14, 2013 21:17 Beiträge: 588
Programmiersprache: C++
acos-Funktionen im Shader zu verwenden ist aus Performance-Sicht auch keine gute Idee. Normalerweise kommt man durch einfache Überlegungen auch ohne aus. Statt clamp(dot, 0.0, 1.0) kann man auch max(dot, 0.0) verwenden. Größer als 1 kann dein Skalarprodukt ja ohnehin nicht werden. Übrigens solltest du floats stets als 0.0 und 1.0 schreiben, nicht als 0 und 1 (das sind ints). Einfache Beleuchtungsshader findest du übrigens auch in unserer Shadersammlung.
_________________ So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)
Registriert: Mi Aug 14, 2013 21:17 Beiträge: 588
Programmiersprache: C++
mathias hat geschrieben:
Stimmt es, das "clamp" folgendes macht ?
Ja.
mathias hat geschrieben:
Kann es sein. das dot ein negativer Wert ausgeben kann ?
Ja. Wenn du zwei Vektoren der Länge 1 hast (d.h. wenn du sie vorher normalisiert hast), gibt das Skalarprodukt der Vektoren sozusagen an, wie ähnlich die Vektoren sind. Beispiele:
Zeigen sie in exakt die gleiche Richtung, ist das Ergebnis 1.
Zeigen sie hingegen in genau entgegengesetzte Richtung, kommt -1 heraus.
Zueinander senkrechte Vektoren führen zu 0.
Das Skalarprodukt zweier Vektoren, die fast in die gleiche Richtung zeigen (aber nicht genau), ist z.B. 0.9.
Deswegen eignet sich das Skalarprodukt auch so schön für Lichtberechnungen. Man kann damit ausrechnen, wie sehr ein Normalenvektor zu einer Lichtquelle hin zeigt. Ist er genau zur Lichtquelle hin gerichtet, resultiert das in einer maximalen Beleuchtung. Alles was eher von der Lichtquelle weg als zu ihr hin zeigt, führt zu einem negativen Skalarprodukt. Das diesen Fall fängt man mit max(dot(), 0.0) oder einem äquivalenten clamp(dot(), 0.0, 1.0) ab, so dass solche Flächen mit der Stärke 0 beleuchtet werden.
Mit Winkeln zu arbeiten, ist hier überhaupt nicht notwendig, weil das dot-Produkt selbst bereits so schöne Eigenschaften hat. Es ist, wie gesagt, der Kosinus des Winkels – vorausgesetzt die Vektoren haben die Länge 1.
_________________ So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)
Ich habe da mal ein bisschen rumprobiert, so das man das Ergebnis grafisch sehen kann. So kann ich besser nachvollziehen, was die Beleuchtung macht. Mit Arccos ( gelb ) ist es absolut linear. Das sieht man bei der Mesh auch gut, wen dies 90° zum Licht verdreht ist, ist dies Grau. Mit max ( blau ) ist die Mesh ab 90° schon schwarz. Die rote Linie zeigt das Skalarprodukt nativ an.
Das es mit Arccos bei 90° auch Schwarz wird, kann man anpassen. ( grün )
Ab ich denke, wie du sagst, ist es am besten, man nimmt das Skalarprodukt direkt, da dies am wenigsten Rechenaufwand gibt. Der Fehler, das Skalar ein Radius hat, und Arccos Linear ist, kann man ignorieren.
Wen ich dies angucke, kann man anstelle von Vektoren auch nur ein Float an dot übergeben, was bringt dies ? Für eine Winkelrechnung, muss man doch immer mindestens ein X und Y haben, oder täusche ich mich da ?
Registriert: Mi Aug 14, 2013 21:17 Beiträge: 588
Programmiersprache: C++
Das liegt daran, dass die dot-Funktion allgemein spezifiziert ist:
Code:
floatdot(genType x, genType y)
Für genType kannst du jeden Vektortyp einsetzen - z.B. vec2, vec3, vec4, ivec3, uve4 oder eben auch float, was man ja als so eine Art eindimensionaler Vektor auffassen kann. Die GLSL-Spezifikation wäre halt einige Seiten länger, wenn man alle eingebauten Funktionen für jeden Typ explizit ausbuchstabiert hätte. Von der Semantik her ist ja auch klar, was passiert:
Code:
floatdot(genType x, genType y)
{
return x.x*y.x
+ x.y*y.y// wenn mindestens 2 Komponenten
+ x.z*y.z// wenn mindestens 3 Komponenten
+ x.w*y.w;// wenn mindestens 4 Komponenten
}
Wenn die Vektoren nur eine Komponente haben, ist das Skalarprodukt halt nur noch eine ganz normale Multiplikation. Gäbe es in GLSL Typen wie vec291, würden da halt 291 Multiplikationen und 290 Additionen stattfinden. Das Prinzip ist aber immer das gleiche. Das Skalarprodukt ist ja auch nicht nur da, um Winkel auszurechnen. Das ist nur eine Möglichkeit, die sich eben aus der grafischen Interpretation ergibt.
_________________ So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)
Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.