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

Aktuelle Zeit: Fr Jul 11, 2025 07:14

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Mi Feb 28, 2007 16:47 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Mär 09, 2005 15:54
Beiträge: 372
Wohnort: München
Programmiersprache: Delphi, C#, FPC
Ich versuche gerade, eine Spiegelung per Stencil-Puffer zu realisieren. Bisher klappt alles ganz gut, nur das ich eine einschränkung habe, die mir nicht so ganz gefällt:

Ich skaliere die Spiegelfläche mit Hilfe von glScale(1, -1, 1) um eine Spiegelung am Boden zu erziehlen. Doch ich möchte jetzt nicht nur waagerecht spiegeln, sondern auch z.B. an einer um 45° gedrehten und 70° geneigten Oberfläche (nur so als Beispiel).

Von der Oberfläche (ist jetzt mal einfach ein Viereck), kenne ich alle 4 Punke und somit auch den Normalenvektor.

Wenn ich jetzt die Spiegelungsroutine richtig verstanden habe, müsste ich jetzt die komplette Welt per glScale(x, y, z) skalieren, um ein korrektes Spiegelbild zu bekommen. Doch wie komme ich auf x, y und z? Den Normalenvektor einfach zu invertieren reicht ja nicht (sonst würde das glScale(1, -1, 1) nicht funzen, da der nVektor (0, 1, 0) ist)

_________________
Aktuelles Projekt: Gael - Development Blog
Website: LightBlackSoft.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Feb 28, 2007 16:56 
Offline
DGL Member

Registriert: So Aug 20, 2006 23:19
Beiträge: 564
Ich denke, das ist gar nicht so einfach. Du solltest ja bedenken, dass man die ebene um so ca. unendlich verschiedene Achsen neigen kann. Das heißt, da musst du dir noch etwas genaueres zb eine Neigungsachse einfallen lassen, sonst wird das kaum was werden. Wenn du diese Achse hast, sollte sich der Rest über das Skalaprodukt errechnen lassen:
cos y = Vektor1 Skala Vektor 2 / (Laenge(Vektor1) * Laenge(Vektor2);


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Feb 28, 2007 17:23 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Mär 09, 2005 15:54
Beiträge: 372
Wohnort: München
Programmiersprache: Delphi, C#, FPC
Hoffe ich hab dich richtig verstanden:

Durch einen zweiten Vektor (z.B. p1->p2; wobei p1 und p2 im Viereck liegen) würde ich die Ebene eindeutig machen? Und dann übers Skalarprodukt usw?

An sich klingt das ja schon sehr vielversprechend. Doch wie komme ich auf die anderen beiden Variablen; x und z?

_________________
Aktuelles Projekt: Gael - Development Blog
Website: LightBlackSoft.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Feb 28, 2007 18:14 
Offline
DGL Member

Registriert: Do Mai 30, 2002 18:48
Beiträge: 1617
Also ich würde das so angehen: Spiegelmatrizen sind immer dieser 3x3 Matrix ähnlich:
Code:
  1. -1 0 0
  2.  0 1 0
  3.  0 0 1
  4.  

Du musst nur das Koordinatensystem finden, in dem die Matrix so aussieht. Das geht aber leicht. Es muss sich um ein Orthonormalsystem handeln und einen Basisvektor kennst du bereits - nämlich deine Normale. Fehlen noch zwei weitere Vektoren, die du fast beliebig wählen kannst, sie müssen nur Orthonormal sein. Nimm dazu deinen Normalenvektor her. Suche dir die Komponente des Vektors heraus, die den kleinsten Betrag aufweist. Setze diese Komponente auf 1. Bilde das Kreuzprodukt aus Normalenvektor und dem eben bestimmten Vektor. Wir nennen diesen einmal b2. Normiere b2 (so skalieren, daß er Länge 1 besitzt). Jetzt bilde das Kreuzprodukt aus n und b2, nenne diesen Vektor b3. Dieser ist bereits normiert und du hast eine Basis aufgespannt, in der die Gewünschte Spiegelung genau wie oben aussieht. Damit kennen wir aber auch schon eine Rotationsmatrix, die unser Koordinatensystem wieder ins globale Koordinatensystem zurückdreht: Man schreibt dazu einfach n, b1, b2 nebeneinander und tue so als wäre es eine Matrix K. Die Einträge sehen dann so aus:
Code:
  1. n[1] b2[1] b3[1]
  2. n[2] b2[2] b3[2]
  3. n[3] b2[3] b3[3]
  4.  

Transponieren wir diese Matrix K, erhalten wir die inverse Matrix K^-1 (Eigenschaft von Rotationsmatrizen.). Sieht so aus:
Code:
  1.  n[1]  n[2]  n[3]
  2. b2[1] b2[2] b2[3]
  3. b3[1] b3[2] b3[3]
  4.  

Diese Matrix dreht also unser globales Koordinatensystem ins Koordinatensystem unserer Drehmatrix. Jetzt müssen wir also nur noch die Matrizen zusammenmultiplizieren:
Code:
  1. KSK^-1
  2.  

Diese Indexschlacht beim zusammenmultiplizieren überlasse ich Dir. Im Matrixartikel im Wiki steht im Bedarfsfall wie das geht - falls Du es nicht wissen solltest (ansonsten ist das Wissen, das man sich für Grafik ganz schnell aneigenen sollte).
Soweit so gut. Wahrscheinlich willst Du die Sache jetzt noch als OpenGl Matrix haben. Gibts aber ganz einfach: Man schreibt an die enstandene Matrix rechts unten noch eine 1 hin und füllt nach oben und links jeweils von der 1 ausgehend mit Nullen auf. Schon hat man aus einer 3x3 Matrix eine passende 4x4 OpenGl Matrix gemacht.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Mär 02, 2007 16:21 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Mär 09, 2005 15:54
Beiträge: 372
Wohnort: München
Programmiersprache: Delphi, C#, FPC
Also ich hab das gestern Abend mal ausprobiert, doch so ganz scheint das nicht zu klappen. Ich poste mal meinen Quelltext:

Code:
  1.  
  2. // (...)
  3. var FNormal  : TGLVectorf3;
  4.     FTNormal : TGLVectorf3;
  5.     FB2      : TGLVectorf3;
  6.     FB3      : TGLVectorf3;
  7.     FMatrix  : array[0..15] of single;
  8.  
  9. // (...)
  10. begin
  11.   // Zuerst die kleinste Komponente suchen und gleich 1 setzen
  12.   FTNormal := FNormal;
  13.   if FTNormal [0] < FTNormal [2] then
  14.   begin
  15.     if FTNormal [0] < FTNormal [1] then
  16.        FTNormal [0] := 1
  17.     else
  18.        FTNormal [1] := 1;
  19.   end else
  20.   begin
  21.     if FTNormal [1] < FTNormal [2] then
  22.        FTNormal [1] := 1
  23.     else
  24.        FTNormal [2] := 1;
  25.   end;
  26.  
  27.   // Jetzt das Kreuzprodukt aus Normalenvektor und den eben erstellten Vektor
  28.   FB2 := Vector_CrossProductf3(FNormal, FTNormal);
  29.   // Normieren ...
  30.   FB2 := Vector_Normalizef3(FB2);
  31.   // Kreuzprodukt aus Normal-Vektor und B2
  32.   FB3 := Vector_CrossProduct(FNormal, FB2);
  33.  
  34.   // und jetzt die Umwandlung in eine Matrix
  35.   FMatrix[0]  := FNormal[0];
  36.   FMatrix[1]  := B2[0];
  37.   FMatrix[2]  := B3[0];
  38.   FMatrix[3]  := 0;
  39.   FMatrix[4]  := FNormal[1];
  40.   FMatrix[5]  := B2[1];
  41.   FMatrix[6]  := B3[1];
  42.   FMatrix[7]  := 0;
  43.   FMatrix[8]  := FNormal[2];
  44.   FMatrix[9]  := B2[2];
  45.   FMatrix[10] := B3[2];
  46.   FMatrix[11] := 0;
  47.   FMatrix[12] := 0;
  48.   FMatrix[13] := 0;  
  49.   FMatrix[14] := 0;
  50.   FMatrix[15] := 1;
  51.  
  52.   // Jetzt habe ich die Matrix, jetzt rendern
  53.   { Kameraposition setzen }
  54.   GLCamera.DoRender();
  55.  
  56.   glPushMatrix();
  57.     glMultiMatrixf(@FMatrix);
  58.     FLevel.DoRender(ADeltaTime, ATotalTime);
  59.   glPopMatrix();
  60.  


Ich glaub ich hab den Begriff "glMultiMatrixf" noch nicht ganz verstanden. Oder habe ich wo anders noch was nicht ganz kappiert?

_________________
Aktuelles Projekt: Gael - Development Blog
Website: LightBlackSoft.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Mär 02, 2007 18:46 
Offline
DGL Member

Registriert: Do Mai 30, 2002 18:48
Beiträge: 1617
Also zwei Dinge die ich gesehen habe:
1. Du suchst nicht die Betragsmäßig kleinste Komponente, sondern die absolut kleinste. Das ganze mit Betrag zu machen hätte schon seinen sinn.
2. Du musst die 3 angegebenen Matrizen miteinander multiplizieren - mach das am besten auf einem Blatt Papier. Diese Matrix muss dann mit MultMatrix weitergereicht werden. Bislang rechnest du nur mit K^-1. Diese beschreibt aber nur eine Drehung. Du musst stattdessen K*S*(K^-1) verwenden, dann sollte die Sache schon besser klappen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Apr 08, 2007 13:54 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Mär 09, 2005 15:54
Beiträge: 372
Wohnort: München
Programmiersprache: Delphi, C#, FPC
So, ICH HABS ENDLICH GESCHAFFT (eine Lösung zu finden):

Da ich ja nicht geizig seien will:
Code:
  1.  
  2. function BuildReflectionMatrix(normalVector: TGLVectorf4): TGLMatrixf4;
  3. begin
  4.   result[0, 0] := -2 * normalVector[0] * normalVector[0] + 1;
  5.   result[0, 1] := -2 * normalVector[0] * normalVector[1];
  6.   result[0, 2] := -2 * normalVector[0] * normalVector[2];
  7.   result[0, 3] :=  0;
  8.  
  9.   result[1, 0] := -2 * normalVector[1] * normalVector[0];
  10.   result[1, 1] := -2 * normalVector[1] * normalVector[1] + 1;
  11.   result[1, 2] := -2 * normalVector[1] * normalVector[2];
  12.   result[1, 3] :=  0;
  13.  
  14.   result[2, 0] := -2 * normalVector[2] * normalVector[0];
  15.   result[2, 1] := -2 * normalVector[2] * normalVector[1];
  16.   result[2, 2] := -2 * normalVector[2] * normalVector[2] + 1;
  17.   result[2, 3] :=  0;
  18.  
  19.   result[3, 0] := -2 * normalVector[3] * normalVector[0];
  20.   result[3, 1] := -2 * normalVector[3] * normalVector[1];
  21.   result[3, 2] := -2 * normalVector[3] * normalVector[2];
  22.   result[3, 3] := 1;
  23. end;
  24.  
  25. // hier ein bespiel, die die szene anhand des dreiecks spiegelt
  26. procedure RenderReflection(v1, v2, v3: TGLVectorf3);
  27. var nVec: TGLVectorf4;
  28.      mat  : TGLMatrixf4;
  29. begin
  30.   nVec := normalize(cross((v1-v2), (v1-v3)));
  31.   nVec[3] := -(nVec[0]*v1[0] + nVec[1]*v1[1] + nVec[2]*v1[2]);
  32.  
  33.   mat := BuildReflectionMatrix(nVec);
  34.  
  35.   glPushMatrix();
  36.     glMultMatrixf(@mat);
  37.     RENDER_SCENE();
  38.   glPopMatrix();
  39. end;
  40.  
  41.  

_________________
Aktuelles Projekt: Gael - Development Blog
Website: LightBlackSoft.com


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


Wer ist online?

Mitglieder in diesem Forum: Google [Bot] und 18 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:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.009s | 15 Queries | GZIP : On ]