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

Aktuelle Zeit: Fr Jul 18, 2025 11:13

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



Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Frage zu 2D mit gluProject
BeitragVerfasst: Di Aug 24, 2004 16:34 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 28, 2004 10:59
Beiträge: 9
Wohnort: Neustrelitz / Meckl.-Vorp.
Hallo,

Ich habe Probleme bei der Positionierung von 2D-Grafik.
Ich habe eine 3D-Darstellung von Meßwerten mitsamt Koordinatensystem und möchte an die Achsen Beschriftungen anbringen. Dazu berechne ich mir die Position in 3D (das klappt noch). Dann hole ich mir
mit gluProject die 2D-Position. Diese ist innerhalb des Viewport. Anschließend rechne ich diese Position noch auf meinen front clipping plane Bereich um, da sie sonst außerhalb des viewing volumes liegt.
Wenn ich jetzt mit glPrint einen Text an die Stelle setze, stimmt die Position nur ungefähr. Sie bewegt sich aber korrekt mit der Karte mit.
Zu Testzwecken habe ich versucht in 2D Dreiecke, deren Position ich genauso berechnet habe, auf entsprechende 3D-Dreiecke zu legen. Ich kriege sie aber nicht deckungsgleich hin, nicht mal ansatzweise.

Hat jemand ähnliche Probleme oder einen Tip?

Gruß,

diskdruide.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Aug 24, 2004 20:14 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Ohne die wichtigen Quellcodestellen ist Helfen hier schwer. Hab selbst schonmal mit gluProject 3D-Objekte beschriftet, hatte aber keine solchen Probleme. Also poste am besten mal die relevanten Codestellen oder sag mal genauer wie du das machst.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Code
BeitragVerfasst: Mi Aug 25, 2004 09:29 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 28, 2004 10:59
Beiträge: 9
Wohnort: Neustrelitz / Meckl.-Vorp.
Hallo,

Ich poste mal den Code ab der Stelle, wo es interessant wird:
Es handelt sich um eine Prozedur, die ein Label an einen Skalenstrich zeichnen soll und wird jedesmal gerufen, wenn ein Skalenstrich gezeichnet worden ist.

Code:
  1.  
  2. procedure TScaledAxis.DrawPitchLineLabel;
  3. var LabelString: PChar;        
  4.     GraphicCurrentLabelPoint: TVector;  
  5.     GraphicCurrentLabelPoint2D_Array: Array[0..2] of Double;
  6.     GraphicCurrentLabelPoint2D_ViewPort: TVector;
  7.     GraphicCurrentLabelPoint2D_Clip_X, GraphicCurrentLabelPoint2D_Clip_Y: Single;
  8.     LabelTextExtension: TSize;
  9. begin
  10.   LabelString := 'Test';         //in the meantime: placeholder
  11.   LabelTextExtension := FCanvas.TextExtent(LabelString);  
  12.       //get the dimensions of the textlabel in pixels, is supported by TCanvas
  13.   FTextDistance := Magnitude(Vector(LabelTextExtension.cx, LabelTextExtension.cy, 0));  
  14.       //max label elongation is along the diagonal
  15.  
  16.   glPushMatrix;   //this is needed to save the already process graphics
  17.   glLoadIdentity;    //move to origin and then
  18.   glTranslatef(0, 0, -(cvpnear+1));
  19.      //move one step into the viewing volume, cvpnear = 0 here
  20.  
  21.   GraphicCurrentLabelPoint := CorrectGraphicPoint(FGraphicCurrentPoint);  
  22.       //CorrectGraphicPoint is a function that turns the y coordinate upside down. Because this was already done in previous processing steps, it has to be revoked here to allow another operation on it.
  23.  


Bis hier nur Deklaration und Initialisierung.

Code:
  1.  
  2.   //only for the x axis
  3.   if (FAxisMode = amX) then begin  
  4.      //only if x axis is in front            
  5.     if ((FAxesToDraw[0] = atFront) or (FAxesToDraw[1] = atFront)) then  
  6.        //get the label to the 'right' side of the axis, where the pitch lines are also
  7.       GraphicCurrentLabelPoint := CorrectGraphicPoint(AddVectors(GraphicCurrentLabelPoint, ScalarProduct(FOrthonormalVector, FTextDistance)))  
  8.     //only if x axis is behind the map
  9.     else if ((FAxesToDraw[0] = atBack) or (FAxesToDraw[1] = atBack)) then  
  10.       //get the label to the 'left' side of the axis, where the pitch lines are also
  11.      GraphicCurrentLabelPoint := CorrectGraphicPoint(SubVectors(GraphicCurrentLabelPoint, ScalarProduct(FOrthonormalVector, FTextDistance)))  
  12.  


Darauffolgend der Teil, der die 3D-Position des Labels berechnet (CurrentGraphicLabelPoint). Ich habe es hier auf den X-Achsen-Fall zusammengekürzt. Die if-Abfrage ist im Code vollständig und funktioniert, daß kann ich anhand von Markierungsdreiecken sehen.

Jetzt wird es interessant:
Code:
  1.  
  2.   gluProject(GraphicCurrentLabelPoint.X, GraphicCurrentLabelPoint.Y, GraphicCurrentLabelPoint.Z, FModelViewMatrix, FProjectionMatrix, FViewPortVector, @GraphicCurrentLabelPoint2D_Array[0], @GraphicCurrentLabelPoint2D_Array[1], @GraphicCurrentLabelPoint2D_Array[2]);
  3.      //OpenGL projects a 3D graphic point on a 2D plane by using the gluProject functionality
  4.  
  5.   GraphicCurrentLabelPoint2D_ViewPort := SubVectors(Vector(GraphicCurrentLabelPoint2D_Array[0], GraphicCurrentLabelPoint2D_Array[1], GraphicCurrentLabelPoint2D_Array[2]), Vector((Round(LabelTextExtension.cx / 2)), (Round(LabelTextExtension.cy / 2)), 0));
  6.     //it actually is adapted to the viewport, but it was the graphic point, where the size of the label was not considered. This is done by subtracting their vectors
  7.  
  8.   GraphicCurrentLabelPoint2D_Clip_X := TranslateViewPortToClipWindow_X(GraphicCurrentLabelPoint2D_ViewPort.X);
  9.   GraphicCurrentLabelPoint2D_Clip_Y := TranslateViewPortToClipWindow_Y(GraphicCurrentLabelPoint2D_ViewPort.Y);
  10.     //translates the 2D ViewPort coordinates to the front plane viewport, which is smaller, before that the values where also inside the viewport but adapted to the dimensions in spacial depth (where the map is situated)
  11.  


Ich hole mir mit gluProject die Position des 3D-Punktes und speichere sie in einem Array (GraphicCurrentLabelPoint2D_Array). Als berechne ich mir die Stelle, die die Mitte des Labels darstellt, wenn man es an der vorher berechneten Position anfügt (und speichere sie in GraphicCurrentLabelPoint2D_ViewPort). Schließlich rechne ich noch den X- und Y-Wert dieser Position auf das vordere Clipping Plane um (Funktionen siehe unten).

Code:
  1.  
  2.   glRasterPos2f(GraphicCurrentLabelPoint2D_Clip_X, -GraphicCurrentLabelPoint2D_Clip_Y);
  3.     //sets the current position, which is on the front viewing plane, so to say, on the screen
  4.   glPrint(LabelString, FFontBase);
  5.     //and puts the label there
  6.  
  7.   glPopMatrix;
  8.     //getting back all the other graphics, which are lying far behind the labels (spacial), but labels will appear, as they were drawn directly to the axes and their pitch lines
  9.  


Der Rest ist dann nur noch: 2D-Position nehmen und das Label da hinschreiben.

Hier noch die Translate-Funktionen:

Code:
  1.  
  2. function TScaledAxis.TranslateViewPortToClipWindow_X(Source_X: Single): Single;
  3. begin
  4.   result := (cvfpleft + (((abs(cvfpleft) + abs(cvfpright)) * Source_X) / FViewPortVector[2]));
  5. end;
  6.  
  7.  
  8. function TScaledAxis.TranslateViewPortToClipWindow_Y(Source_Y: Single): Single;
  9. begin
  10.   result := (cvfptop + (((abs(cvfptop) + abs(cvfpbottom)) * Source_Y) / FViewPortVector[3]));
  11. end;
  12.  

Die cvfp-Werte sind konstante Werte, die das front clipping plane des viewing volumes beschreiben, sie sind zu Programmbeginn definiert und sollten richtig sein (getestet) (cvfp =^ constant value front plane)

Ich habe versucht den Code lesbar zu schreiben, ich hoffe, es geht.
Leider haut irgendwas nicht hin. Die Labels haben nur ungefähr die richtige Position. Wenn ich Markierungsdreiecke verwenden, diese zeichne und deren Punkte mit diesem Algorithmus in 2D umrechne
(dann ohne die Labelgröße) und auch zeichne liegen sie recht weit auseinander. Also nicht mal ansatzweise
deckungsgleich. Den Code dafür kann ich bei Bedarf auch posten.

Ist irgendwo ein Fehler zu sehen?
Gruß,
diskdruide.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Aug 25, 2004 16:16 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Wenn ich da oben nicht irgendwas übersehen habe, dann interpretierst du da etwas falsch. Der Ursprung des Fensters liegt bei OpenGL unten/links, nicht wie bei Windows oben/links. Du musst also die von gluProject ermittelte Y-Koordinat von der Höhe des Viewports abziehen um die korrekte Position zu bekommen.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Lösung gefunden
BeitragVerfasst: Do Aug 26, 2004 10:49 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 28, 2004 10:59
Beiträge: 9
Wohnort: Neustrelitz / Meckl.-Vorp.
Danke für den Tip.
Bei den 3D-Koordinaten hatte ich das soweit berücksichtigt - indem ich eine Funktion CorrectGraphicPoint(..3D-Punkt..) habe. Die tauscht das Vorzeichen der Y-Koordinate. Die kann ich so einsetzen, daß vor Rechenschritten in die eine und vor Zeichenschritten in die andere Richtung umgerechnet wird. Wahrscheinlich nicht die optimalste Lösung.

In der Umrechnung zu 2D waren oben und unten aber vertauscht.
Auf jeden Fall habe ich die beiden Translate-Funktionen auf den Tip hin nochmal überarbeitet, was schon etwas bessere Ergebnisse brachte und für die, die es interessiert noch die Lösung des Problems, auf die ich nach langem Suchen gestoßen bin: Ich hatte den ViewPort an einer Stelle des Programms auf ein bestimmtes Seitenverhältnis gezwungen, um Verzerrungen bei Fenstergrößenänderungen zu vermeiden und nicht beachtet, daß der ViewPort nun nicht mehr das ganze Fenster ausfüllt.

Hier der berichtigte Code:
Code:
  1.  
  2. function TScaledAxis.TranslateViewPortToClipWindow_X(Source_X: Single): Single;
  3. var Factor: single;
  4. begin
  5.   result := (cvfpleft + (((cvfpright - cvfpleft) * (Source_X - FViewPortVector[0])) / FViewPortVector[2]));
  6. end;
  7.  
  8.  
  9. function TScaledAxis.TranslateViewPortToClipWindow_Y(Source_Y: Single): Single;
  10. begin
  11.   result := (cvfptop + (((cvfpbottom - cvfptop) * (Source_Y - FViewPortVector[1])) / FViewPortVector[3]));
  12. end;
  13.  


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


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 14 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.007s | 15 Queries | GZIP : On ]