Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Mär 28, 2024 10:12

Foren-Übersicht » Programmierung » Mathematik-Forum
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 12 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Fr Mai 26, 2017 16:42 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
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.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Mai 26, 2017 17:52 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
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:
  1. R1 = (P-C) / |P-C|
  2. 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:
  1. float winkel(vec3 p, vec3 q, vec3 c){
  2.   vec3 r1 = normalize(p-c);
  3.   vec3 r2 = normalize(q-c);
  4.   return acos(dot(r1, r2));
  5. }

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Mai 26, 2017 19:36 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Danke, genau dies habe ich gesucht. :)

Ich habe mit Google noch etwas diskretes gefunden, ich hatte zuerst nur falsch gesucht. :oops:
http://ne.lo-net2.de/selbstlernmaterial ... _ww_gw.pdf
Code:
  1.   winkel := arccos((x1 * x2 + y1 * y2 + z1 * z2) / (sqrt(x1 * x1 + y1 * y1 + z1 * z1) * sqrt(x2 * x2 + y2 * y2 + z2 * z2)));  


Aber da ich es im Shader anwenden will, ist deine Lösung natürlich besser. :idea:

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Mai 26, 2017 20:47 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich habe gerade eine sehr einfache Beleuchtung gebaut.
Code:
  1. #version 330
  2.  
  3. #define PI 3.1415926535897932384626433832795
  4.  
  5. layout (location = 10) in vec3 inPos;    // Vertex-Koordinaten
  6. layout (location = 11) in vec3 inNormal; // Normale
  7.  
  8. out vec4 Color;                          // Farbe, an Fragment-Shader übergeben.
  9.  
  10. uniform mat4 Matrix;                     // Matrix für die Drehbewegung und Frustum.
  11.  
  12. vec3 LightPos = vec3(1.0, 0.0, 0.0);
  13.  
  14. float winkel(vec3 p, vec3 q){
  15.   vec3 r1 = normalize(p);
  16.   vec3 r2 = normalize(q);
  17.   return acos(dot(r1, r2));
  18. }
  19.  
  20. void main(void)
  21. {
  22.   vec3 Normal = mat3(Matrix) * inNormal;
  23.  
  24.   float w = winkel(LightPos, Normal);
  25.   float col = (w / PI);
  26.  
  27.   gl_Position = Matrix * vec4(inPos, 1.0);
  28.   Color = vec4(col, col, col, 0.0);
  29. }

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Jun 01, 2017 20:08 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
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)
Code:
  1. #version 330
  2.  
  3. layout (location = 0) in vec3 inPos;    // Vertex-Koordinaten
  4. layout (location = 1) in vec3 inNormal; // Normale
  5.  
  6. out vec4 Color;                         // Farbe, an Fragment-Shader übergeben.
  7.  
  8. uniform mat4 Matrix;                    // Matrix für die Drehbewegung und Frustum.
  9.  
  10. vec3 LightPos = vec3(1.0, 0.0, 0.0);
  11.  
  12. float winkel(vec3 p, vec3 q){
  13.   vec3 r1 = normalize(p);
  14.   vec3 r2 = normalize(q);
  15.   return clamp(dot(r1, r2), 0, 1);  // clamp anstelle acos
  16. }
  17.  
  18. void main(void)
  19. {
  20.   vec3 Normal = mat3(Matrix) * inNormal;
  21.  
  22.   float col = winkel(LightPos, Normal);
  23.  
  24.   gl_Position = Matrix * vec4(inPos, 1.0);
  25.   Color = vec4(col, col, col, 0.0);
  26. }  


Ich sehe schon, für eine Beleuchtung gibt es fast endlos viele Möglichkeiten.

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jun 02, 2017 07:36 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
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)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jun 02, 2017 19:37 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Stimmt es, das "clamp" folgendes macht ?
Code:
  1. function clamp(f, min, max: single): single;
  2. begin
  3.   if f < min then begin
  4.     Result := min;
  5.   end else if f > max then begin
  6.     Result := max;
  7.   end else begin
  8.     Result := f;
  9.   end;
  10. end;


Zitat:
Statt clamp(dot, 0.0, 1.0) kann man auch max(dot, 0.0) verwenden.

Kann es sein. das dot ein negativer Wert ausgeben kann ?

Was mir immer noch ein Rätsel ist, wieso kann ich "acos" weglassen ?
Und wieso kommt nirgends "Pi" vor ?

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jun 02, 2017 23:37 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
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)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Jun 03, 2017 16:54 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
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.

Code:
  1. function Skalar(x1, y1, x2, y2: single): single;
  2. begin
  3.   Result := ((x1 * x2 + y1 * y2) / (sqrt(x1 * x1 + y1 * y1) * sqrt(x2 * x2 + y2 * y2)));
  4. end;
  5.  
  6. procedure TForm1.FormCreate(Sender: TObject);
  7. var
  8.   i: integer;
  9.   x, y, b: single;
  10. begin
  11.   Chart1LineSeries1.LinePen.Color := clRed;
  12.   Chart1LineSeries2.LinePen.Color := clBlue;
  13.   Chart1LineSeries3.LinePen.Color := clYellow;
  14.   Chart1LineSeries4.LinePen.Color := clGreen;
  15.   for i := 0 to 360 * 2 - 1 do begin
  16.     b := i / 180 * Pi;
  17.     x := sin(b);
  18.     y := cos(b);
  19.  
  20.     Chart1LineSeries1.AddY(Skalar(x, y, 1.0, 0.0));
  21.     Chart1LineSeries2.AddY(max(Skalar(x, y, 1.0, 0.0), 0.0) + 0.01);
  22.     Chart1LineSeries3.AddY(arccos(Skalar(x, y, -1.0, 0.0)) / Pi + 0.02);
  23.     Chart1LineSeries4.AddY(max(arccos(Skalar(x, y, -1.0, 0.0)) / Pi * 2-1.0,0.0));
  24.   end;
  25. end;


Dateianhänge:
Bildschirmfoto vom 2017-06-03 17-52-32.png
Bildschirmfoto vom 2017-06-03 17-52-32.png [ 27.88 KiB | 13554-mal betrachtet ]

_________________
OpenGL
Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Jun 03, 2017 17:01 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich habe noch eine Frage zu dot im Shader.

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 ?
Code:
  1. float dot(float x, float y)  
  2. float dot(vec2 x, vec2 y)  
  3. float dot(vec3 x, vec3 y)  
  4. float dot(vec4 x, vec4 y)

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Jun 04, 2017 08:59 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
Das liegt daran, dass die dot-Funktion allgemein spezifiziert ist:
Code:
  1. float dot(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:
  1. float dot(genType x, genType y)
  2. {
  3.   return x.x*y.x
  4.        + x.y*y.y  // wenn mindestens 2 Komponenten
  5.        + x.z*y.z  // wenn mindestens 3 Komponenten
  6.        + x.w*y.w;  // wenn mindestens 4 Komponenten
  7. }
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)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Jun 04, 2017 16:40 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
@glAwesome

Danke für die Infos, jetzt ist es klar warum dies so ist.

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 12 Beiträge ] 
Foren-Übersicht » Programmierung » Mathematik-Forum


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 15 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.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.104s | 21 Queries | GZIP : On ]