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

Aktuelle Zeit: Do Apr 25, 2024 07:29

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



Ein neues Thema erstellen Auf das Thema antworten  [ 11 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: glUnProject
BeitragVerfasst: Fr Mai 03, 2013 10:30 
Offline
DGL Member

Registriert: Do Mär 21, 2013 14:57
Beiträge: 51
Programmiersprache: C#,C++
So da bin ich wieder mit einer neuen Frage. Ich benötige die Position des Mauszeigers in Abhängigkeit vom augenblicklich
gültigen Modelview - Koordinatensystem und stieß auf glUnProject. Leider ist diese Funktion veraltet, weswegen VS bei
mir permanent mosert. Deswegen habe ich die Funktion selbst implementiert. Sie funktioniert soweit ganz gut, jedoch beziehen
sich die Mauskoordinaten immer noch nicht auf das Modelview - Koordinatensystem.. zumindest nicht korrekt. Im folgenden mal
der Code und ein paar Beispielbilder. Die berechnete Mausposition steht im toolstrip am unteren Rand der Anwendung.

Mache ich irgendetwas falsch oder muss ich noch ein paar zusätzliche Berechnungen anstellen!?

Code:
  1.  
  2.         // ****************************************************************************************************
  3.         // Function for computing 3D - position.
  4.         // ****************************************************************************************************
  5.         public Vector3 GetMouse3DPos(int mousePos_X, int mousePos_Y)
  6.         {
  7.             var viewport = new int[4];
  8.             Matrix4 modelview, projection;
  9.  
  10.             // Get the needed matrix informations for computing mouse 3D - position.
  11.             GL.GetInteger(GetPName.Viewport, viewport);
  12.             GL.GetFloat(GetPName.ModelviewMatrix, out modelview);
  13.             GL.GetFloat(GetPName.ProjectionMatrix, out projection);
  14.  
  15.             var t = new float[1];
  16.             GL.ReadPixels(mousePos_X, (viewport[3] - mousePos_Y), 1, 1, PixelFormat.DepthComponent, PixelType.Float, t);
  17.  
  18.             // Compute 3D position.
  19.             Vector3 mouse_3D = new Vector3();
  20.  
  21.             try
  22.             {
  23.                 mouse_3D = new Vector3(UnProject(new Vector3(mousePos_X, viewport[3] - mousePos_Y, t[0]), modelview, projection, viewport));
  24.             }
  25.             catch (ArgumentException exc)
  26.             {
  27.                 MessageBox.Show(exc.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
  28.             }
  29.            
  30.             Vector3 mouse_out = mouse_3D;
  31.  
  32.             return mouse_out;
  33.         }
  34.  
  35.         // ****************************************************************************************************
  36.         // Self implemented glUnProject.
  37.         // ****************************************************************************************************
  38.         private Vector3 UnProject(Vector3 screen, Matrix4 modelview, Matrix4 projection, IList<int> viewport)
  39.         {
  40.             var pos = new Vector4()
  41.             {
  42.                 X = ((screen.X - viewport[0]) / viewport[2]) * 2.0f - 1.0f,
  43.                 Y = ((screen.Y - viewport[1]) / viewport[3]) * 2.0f - 1.0f,
  44.                 Z = screen.Z * 2.0f - 1.0f,
  45.                 W = 1.0f
  46.             };
  47.  
  48.             var pos2 = Vector4.Transform(pos, Matrix4.Invert(Matrix4.Mult(modelview, projection)));
  49.             var posOut = new Vector3(pos2.X, pos2.Y, pos2.Z);
  50.  
  51.             if (posOut.Z == 0.0f)
  52.             {
  53.                 throw new ArgumentException("Error: Division throught 0!", "posOut.Z");
  54.             }
  55.             else
  56.                 return (posOut / pos2.W);
  57.         }


Die Funktion "Get3DMousePos" wird in meiner Form bei jedem Durchlauf aufgerufen und ich überreiche ihr die Mausposition am Bildschirm
bezogen auf glControl. (Nur zur Info - ich verwende OpenTK aufgrund der nötigen Verwendung von C#).

In den folgenden Bildern wird die Mausposition durch den roten Kreis inkl. Punkt dargestellt.



Ziel des Ganzen soll es letztendlich sein einen Punkt auf einem 3D Körper auszuwählen, danach einen zweiten und deren Distanz zu bestimmen.
Ähnlich einer Bemaßung in CAD - Programmen.


Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

_________________
_______________________________________
Lets move over mountains and through valleys:
GL.Map2(,,,,,,,,,)
GL.MapGrid2(,,,,,,,,,)
GL.EvalMesh2(,,,,,,,,,)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glUnProject
BeitragVerfasst: Fr Mai 03, 2013 14:09 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Apr 13, 2011 22:05
Beiträge: 218
Programmiersprache: Lazarus/FPC
Ich hab da mal vor einiger Zeit 2 C++ -Methoden aus dem Netz gepickt und in delphi übersetzt:

Sie wandeln 2D (also Mauszeiger z.B) in 3D Koordinaten des aktuellen Modelviews um, bzw auch umgekehrt, wenn du einen 3D Punkt hast kannst du dessen Bildschirmkoordinaten (2D) ausgeben lassen.
Ergebnis ist immer ein tglvectord3, ein array [0..2] of gl_Float.


Code:
  1.  
  2. function to3d(X, Y: Integer): TGLVectord3;
  3. var
  4.   viewport: TGLVectori4;
  5.   modelview: TGLMatrixd4;
  6.   projection: TGLMatrixd4;
  7.   Z: TGLFloat;
  8.   Y_new: Integer;
  9. begin
  10.   glGetDoublev(GL_MODELVIEW_MATRIX, @modelview);
  11.   glGetDoublev(GL_PROJECTION_MATRIX, @projection);
  12.   glGetIntegerv(GL_VIEWPORT, @viewport);
  13.   Y_new := viewport[3] - Y;
  14.   glReadPixels(X, Y_new, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, @Z);
  15.   gluUnProject(X, Y_new, Z, modelview, projection, viewport, @result[0],
  16.     @result[1], @result[2]);
  17. end;
  18.  
  19. // 3D-Koordinaten in Mauskoordinaten
  20. function to2d(X, Y, Z: real): TGLVectord3;
  21. var
  22.   viewport: TGLVectori4;
  23.   modelview: TGLMatrixd4;
  24.   projection: TGLMatrixd4;
  25. begin
  26.   glGetDoublev(GL_MODELVIEW_MATRIX, @modelview);
  27.   glGetDoublev(GL_PROJECTION_MATRIX, @projection);
  28.   glGetIntegerv(GL_VIEWPORT, @viewport);
  29.   gluProject(X, Y, Z, modelview, projection, viewport, @result[0], @result[1],
  30.     @result[2]);
  31. end;


lg

_________________
Ich teile manchmal heimlich durch Null. - Alber Einstein


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glUnProject
BeitragVerfasst: Fr Mai 03, 2013 19:27 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Nov 30, 2011 21:41
Beiträge: 136
Wohnort: Bad Vilbel
Programmiersprache: Delphi 7
Das mit dem Umrechnen ist nicht so ganz einfach, hab das mal selber mit einer First Person Camera probiert. Eigentlich sollte gluUnproject funktionieren (weis nicht warum es dass nicht sollte, weil die Funktion auf der CPU ausgeführt wird). Du musst halt noch den Tiefenwert des Pixels an die Funktion weitergeben (winz). Hatte selber mal ein ähnliches Problem (siehe hier: http://www.delphigl.com/forum/viewtopic.php?f=2&t=10768 ), was ich gelöst hatte, indem ich einfach den geklickten Richtungsvektor mir von gluUnproject ermitteln lassen habe und darauf hin mit dem Kameraposition und diesem Vektor weitergerechnet habe. Wenn du sowieso Koordinaten auf deinem Objekt haben willst, also mit dem Tiefenwert wie auch im Framebuffer kannst du dir das eigentlich sparen und entweder den Code von Ida bzw. den aus der Wiki zu benutzen: http://[url]wiki.delphigl.com/index.php/gluUnProject[/url]

Ich hoffe ich konnte dir weiterhelfen :)

EDIT: http://www.opengl.org/wiki/GluProject_and_gluUnProject_code Das wäre ein Link, der mir damals weitergeholfen hat indem du den Quellcode der gluUnrpoject Funktion siehst ;)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glUnProject
BeitragVerfasst: So Mai 05, 2013 21:23 
Offline
DGL Member

Registriert: Do Mär 21, 2013 14:57
Beiträge: 51
Programmiersprache: C#,C++
Okay ich probier mal alles ein wenig durch. Aber soweit ich das sehe muss ich die Division
durch 0 nicht abfangen in der glUnProject!? Ich probiers am Montag mal aus und schreibe
dann hier wieder wenn was nicht stimmen sollte. Danke!

Nochmal zum Verständnis: glUnProject liefert mir nicht bereits die fertige Position des Maus-
zeigers im 3D - System sondern nur den Richtungsvektor vom Bildschirm aus in die 3D - Ebene
und ich muss das noch mit dem Modelview - Koordinatensystem verrechnen um an die Position
in Abhängigkeit vom aktuellen Modelview - Koordinatensystem zu kommen!?

_________________
_______________________________________
Lets move over mountains and through valleys:
GL.Map2(,,,,,,,,,)
GL.MapGrid2(,,,,,,,,,)
GL.EvalMesh2(,,,,,,,,,)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glUnProject
BeitragVerfasst: Fr Mai 10, 2013 10:31 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Nov 30, 2011 21:41
Beiträge: 136
Wohnort: Bad Vilbel
Programmiersprache: Delphi 7
Doch, doch. gluUnproject sollte dir bereits die Koordinaten im Raum liefern. Da bist du wahrscheinlich durch meinen Thread darauf gekommen, ich habs damals extra geändert, damit ich nur den Richtungsvektor bekomme, aber an sich rechnet gluUnproject gleich in Raumkoordinaten um. ;)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glUnProject
BeitragVerfasst: Mo Mai 13, 2013 09:38 
Offline
DGL Member

Registriert: Do Mär 21, 2013 14:57
Beiträge: 51
Programmiersprache: C#,C++
Alles klar, jetzt funktioniert es mit glUnProject()! Das Problem lag an einer anderen Stelle.

Nur noch eine dumme Frage:
Sobald ich meine Maus auf ein gezeichnetes Objekt bewege gibt mir die Funktion bereits die passenden Koordinaten meines Mauszeigers auf
dem Objekt zurück, ich finde das zwar genial weil es mir Arbeit erspart, aber ist das gewollt? Denn befindet sich mein Mauszeiger nicht auf
einem, von mir "gezeichneten" Körper, werden die Koordinaten relativ groß.

Hier nochmal meine Funktionen:

Code:
  1.  
  2.         public Vector3 GetMouse3DPos(int mousePos_X, int mousePos_Y)
  3.         {
  4.             var viewport = new int[4];
  5.             Matrix4 modelview, projection;
  6.  
  7.             // Get the needed matrix informations for computing mouse 3D - position.
  8.             GL.GetInteger(GetPName.Viewport, viewport);
  9.             GL.GetFloat(GetPName.ModelviewMatrix, out modelview);
  10.             GL.GetFloat(GetPName.ProjectionMatrix, out projection);
  11.  
  12.             var t = new float[1];
  13.             GL.ReadPixels(mousePos_X, (viewport[3] - mousePos_Y), 1, 1, PixelFormat.DepthComponent, PixelType.Float, t);
  14.  
  15.             // Compute 3D position.
  16.             Vector3 mouse_3D = new Vector3();
  17.  
  18.             try
  19.             {
  20.                 mouse_3D = new Vector3(UnProject(new Vector3(mousePos_X, viewport[3] - mousePos_Y, t[0]), modelview, projection, viewport));
  21.             }
  22.             catch (ArgumentException exc)
  23.             {
  24.                 MessageBox.Show(exc.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
  25.             }
  26.            
  27.             Vector3 mouse_out = mouse_3D;
  28.  
  29.             return mouse_out;
  30.         }
  31.  
  32.  
  33.         private Vector3 UnProject(Vector3 screen, Matrix4 modelview, Matrix4 projection, IList<int> viewport)
  34.         {
  35.             var pos = new Vector4()
  36.             {
  37.                 X = ((screen.X - viewport[0]) / viewport[2]) * 2.0f - 1.0f,
  38.                 Y = ((screen.Y - viewport[1]) / viewport[3]) * 2.0f - 1.0f,
  39.                 Z = screen.Z * 2.0f - 1.0f,
  40.                 W = 1.0f
  41.             };
  42.  
  43.             var pos2 = Vector4.Transform(pos, Matrix4.Invert(Matrix4.Mult(modelview, projection)));
  44.             var posOut = new Vector3(pos2.X, pos2.Y, pos2.Z);
  45.  
  46.             if (posOut.Z == 0.0f)
  47.             {
  48.                 throw new ArgumentException("Error: Division through 0!", "posOut.Z");
  49.             }
  50.             else
  51.                 return (posOut / pos2.W);
  52.         }
  53.  

_________________
_______________________________________
Lets move over mountains and through valleys:
GL.Map2(,,,,,,,,,)
GL.MapGrid2(,,,,,,,,,)
GL.EvalMesh2(,,,,,,,,,)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glUnProject
BeitragVerfasst: Mi Mai 22, 2013 09:25 
Offline
DGL Member

Registriert: Do Mär 21, 2013 14:57
Beiträge: 51
Programmiersprache: C#,C++
Nur mal aus Interesse: Ist die Frage meiner letzten Antwort hier so dumm, dass keiner antwortet
oder ist sich keiner bei der Antwort auf die Frage sicher bzw. kennt sie nicht?! ^^

_________________
_______________________________________
Lets move over mountains and through valleys:
GL.Map2(,,,,,,,,,)
GL.MapGrid2(,,,,,,,,,)
GL.EvalMesh2(,,,,,,,,,)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glUnProject
BeitragVerfasst: Mi Mai 22, 2013 09:46 
Offline
DGL Member

Registriert: Do Mär 05, 2009 20:17
Beiträge: 284
Wohnort: Kaiserslautern
nicht sicher ob ich die Frage richtig verstanden habe, aber wenn dich die Koordinaten bei "nicht vorhandener geometrie" stören, kannst du doch das Ergebnis verwerfen, sobald glreadpixels die clearcolor zurückgibt?

jedenfalls wäre das mein Ansatz.. (wenn das die frage war)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glUnProject
BeitragVerfasst: Mi Mai 22, 2013 10:22 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Nov 30, 2011 21:41
Beiträge: 136
Wohnort: Bad Vilbel
Programmiersprache: Delphi 7
@Wölfchen: glReadPixel gibt hier DepthComponent zurück also den Tiefenwert, die Farbe bekommt man garnicht, außer man macht einen weiteren Aufruf von glReadPixels.

@Litefora: Nun warum die Koordinaten so groß werden liegt daran, dass wenn du ins "Leere" klickst, der Tiefenwert dieses Pixels maximal ist (1 glaub ich), das entspräche als Distanz deinem FarClipping Wert. Um das etwas zu veranschaulichen...

glUnproject macht ungefähr Folgendes:
Du übergibts ja der Funktion, sowohl Modelview als auch Projektionsmatrix, daraus weis die Funktion dann ja wo du dich im Raum befindest, in welche Richtung du schaust usw. Daraus weis die Funktion auch schon in welche Richtung sie von der "Kameraposition" aus gehen muss, bzw. in welche Richtung dein Mauszeiger zeigt wenn du klickst. Ein Punkt + ein Richtungsvektor ergeben ja bekannterweise eine Gerade. Damit du jetzt einen Punkt als Ergebnis bekommst, musst du den Tiefenwert noch übergeben, dann wird nämlich ausgerechnet welcher Punkt auf der Gerade diesem Tiefenwert entspricht, und somit wird aus der Gerade ein Punkt.

Wenn jetzt der Tiefenwert nicht gesetzt ist, dann ist der Punkt auf der Gerade natäurlich extrem weit weg, was zu deinen großen Koordinaten führt.

Mögliche Lösung, einfach am Anfang überprüfen wie groß der Tiefenwert ist. Am besten lässt du dir den Tiefenwert ein paar mal ausgeben, wenn du ins Leere klickst, schaust dann wie er sich da verhält und machst dann eine passende if-überprüfung um diese Fälle zu umgehen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glUnProject
BeitragVerfasst: Mi Mai 22, 2013 11:29 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Aug 18, 2007 18:47
Beiträge: 694
Wohnort: Köln
Programmiersprache: Java
Code:
  1. var posOut = new Vector3(pos2.X, pos2.Y, pos2.Z);
  2.  
  3. if (posOut.Z == 0.0f)
  4. {
  5.     throw new ArgumentException("Error: Division through 0!", "posOut.Z");
  6. }
  7.     else
  8.         return (posOut / pos2.W);
  9.  

Sollte hier nicht pos2.W auf 0.0 überprüft werden?

_________________
Es werde Licht.
glEnable(GL_LIGHTING);
Und es ward Licht.


Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"

on error goto next


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glUnProject
BeitragVerfasst: Mi Mai 22, 2013 12:57 
Offline
DGL Member

Registriert: Do Mär 21, 2013 14:57
Beiträge: 51
Programmiersprache: C#,C++
Oh verdammt, ja da hast du recht ^^! Danke!

_________________
_______________________________________
Lets move over mountains and through valleys:
GL.Map2(,,,,,,,,,)
GL.MapGrid2(,,,,,,,,,)
GL.EvalMesh2(,,,,,,,,,)


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


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 98 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.834s | 17 Queries | GZIP : On ]