Darstellung eines Koordinatensystems von schräg oben mit gluLookAt
-
Ich weiß, der Titel ist etwas unspezifisch, deshalb hier nochmal eine genaue Beschreibung:
Ich will eine schräge Ansicht auf ein Koordinatensystem darstellen. Die Achsen beginnen jeweils im Ursprung und sind alle gleich lang. z.B. 10 Einheiten. Die Kamera soll mittels lookAt auf der Hauptdiagonalen des System plaziert sein, z.B. in (20, 20, 20). Sie soll auf den Ursprung blicken.
Die x-Achse ist rot gefärbt, die y-Achse grün und die z-Achse blau.
Soweit so gut.
Nach meinem Vorstellungsvermögen müsste man an der Position (20, 20, 20) folgendes sehen:
- der Ursprung befindet sich in der Mitte
- die rote Achse läuft vom Ursprung nach links unten weg
- die grüne Achse läuft vom Ursprung aus senkrecht nach oben
- die blaue Achse läuft vom Ursprung nach rechts unten wegHier nun aber eine Darstellung der Szene:
Wie man sehen kann, sind x- und z-Achse vertauscht.
Warum ist das so? Ich dachte, OpenGL liegt in den Standardeinstellungen die Rechte-Hand-Regel zugrunde, und gemäß dieser müsste das Bild doch so aussehen, wie von mir beschrieben, oder nicht?
Wer kann mich über meinen Denkfehler aufklären?
Hier noch der Code, er basiert auf GLUT und sollte demnach plattformübergreifend kompilierbar sein:
#include <stdlib.h> #include <GL/gl.h> #include <GL/glut.h> bool fullScreen = false; /* Function prototypes. */ void glutDisplay(void); void glutReshape(int width, int height); void glutIdle(void); void glutMenu(int ID); void glutKeyboard(unsigned char key, int x, int y); void glutSpecial(int keys, int x, int y); void initGL(); void initScene(); void drawSceneGraphics(); void drawAxis(); // surface-specific functions float getMaxWorkspaceSize(); /******************************************************************************* Initializes GLUT for displaying a simple haptic scene. *******************************************************************************/ int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(600, 600); glutCreateWindow("NanoSurface(Creator)Display"); // Set glut callback functions. glutDisplayFunc(glutDisplay); glutReshapeFunc(glutReshape); glutIdleFunc(glutIdle); glutKeyboardFunc(glutKeyboard); glutSpecialFunc(glutSpecial); glutCreateMenu(glutMenu); glutAddMenuEntry("Quit", 0); glutAttachMenu(GLUT_RIGHT_BUTTON); initScene(); glutMainLoop(); return 0; } /******************************************************************************* GLUT callback for redrawing the view. *******************************************************************************/ void glutDisplay() { drawSceneGraphics(); glutSwapBuffers(); } /******************************************************************************* GLUT callback for reshaping the window. This is the main place where the viewing and workspace transforms get initialized. *******************************************************************************/ void glutReshape(int width, int height) { if (height==0) // Prevent A Divide By Zero By { height=1; // Making Height Equal One } glViewport(0,0,width,height); // Reset The Current Viewport glMatrixMode(GL_PROJECTION); // Select The Projection Matrix glLoadIdentity(); // Reset The Projection Matrix gluPerspective( 45.0f, // corresponds to human-eye view angle (GLfloat) width / height, // aspect-ratio of window 0.0f, // start from the beginning 100.0f // nothing beyond this value has to be displayed ); glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix glLoadIdentity(); // Reset The Modelview Matrix } /******************************************************************************* GLUT callback for idle state. Use this as an opportunity to request a redraw. Checks for HLAPI errors that have occurred since the last idle check. *******************************************************************************/ void glutIdle() { glutPostRedisplay(); } /****************************************************************************** Popup menu handler. ******************************************************************************/ void glutMenu(int ID) { switch(ID) { case 0: exit(0); break; } } /******************************************************************************* Initializes the scene. Handles initializing both OpenGL and HL. *******************************************************************************/ void initScene() { initGL(); } /******************************************************************************* Sets up general OpenGL rendering properties: lights, depth buffering, etc. *******************************************************************************/ void initGL() { glShadeModel(GL_SMOOTH); // Enable Smooth Shading glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background glClearDepth(1.0f); // Depth Buffer Setup glEnable(GL_DEPTH_TEST); // Enables Depth Testing glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations } /******************************************************************************* The main routine for displaying the scene. Gets the latest snapshot of state from the haptic thread and uses it to display a 3D cursor. *******************************************************************************/ void drawSceneGraphics() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer // draw axis system drawAxis(); } void drawAxis() { glLoadIdentity(); // place the camera opposite from the origin looking at it gluLookAt( 20.0f, 20.0f, 20.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f ); glBegin(GL_LINES); glColor3f(1.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(10.0f, 0.0f, 0.0f); glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 10.0f, 0.0f); glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 10.0f); glEnd(); } /******************************************************************************* Keyboard handler *******************************************************************************/ void glutKeyboard(unsigned char key, int x, int y) { switch (key) { case 27: // Escape key exit(0); break; case 'F': case 'f': if (fullScreen) { glutReshapeWindow(600, 600); } else { glutFullScreen(); } fullScreen = !fullScreen; break; } } /******************************************************************************* Special function handler (function and arrow keys) *******************************************************************************/ void glutSpecial(int keys, int x, int y) { } /******************************************************************************/Vielen Dank schon mal!
-
gluPerspective( 45.0f, // corresponds to human-eye view angle (GLfloat) width / height, // aspect-ratio of window 0.0f, // start from the beginning 100.0f // nothing beyond this value has to be displayed );Die near-Plane würde ich lieber nicht auf 0 setzen^^.
-
mit "glScalef(GLfloat x,GLfloat y, GLfloat z)" kannst du entlang einer X-Achse spiegeln, indem du einen Wert auf -1 setzt, damit kannst du dein Koordinatensystem anpassen, wie du es willst.
-
Hallo Pellaeon und Krux,
danke Euch beiden schonmal.
Pellaeon schrieb:
gluPerspective( 45.0f, // corresponds to human-eye view angle (GLfloat) width / height, // aspect-ratio of window 0.0f, // start from the beginning 100.0f // nothing beyond this value has to be displayed );Die near-Plane würde ich lieber nicht auf 0 setzen^^.
Danke für den Hinweis (auch wenn ich noch nicht genau kapiert habe, wo dort eine Division durchgeführt wird). Ich hab den Wert jedenfalls auf 0.1 geändert, was aber nichts am Ergebnis ändert.
Krux schrieb:
mit "glScalef(GLfloat x,GLfloat y, GLfloat z)" kannst du entlang einer X-Achse spiegeln, indem du einen Wert auf -1 setzt, damit kannst du dein Koordinatensystem anpassen, wie du es willst.
Danke, so stimmt zwar die Rechte-Hand-Regel wieder, aber die Blickrichtung passt dann wieder nicht.
Mir geht es auch viel mehr darum, zu verstehen, warum es so aussieht, wie es aussieht, als einen schmutzigen Fix reinzubauen, der am Ende womöglich noch mehr Probleme bringt.
-
glBegin(GL_LINES); glColor3f(1.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(10.0f, 0.0f, 0.0f); glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 10.0f, 0.0f); glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 10.0f); glEnd();Die Grafik stimmt schon. Du hast als UpVector bei gluLookAt (0,1,0) angegeben. Also ist die y-Achse bei dir oben. Und dann stimmt dein Bild auch.
Die x-Achse (blaue) geht nach rechts, y (rot) nach oben und z nach vorne. Entspricht genau der "Rechten Hand"-Regel.
-
Hallo Pellaoen,
die Auswirkung des Up-Vectors habe ich ohnehin nicht ganz verstanden. In meiner Vorstellung brauche ich nur den Kamerapunkt und den Blickpunkt, wo oben ist, ist dann doch für die Ansicht erstmal uninteressant.
Aber zurück zur Hand: Nimm Dir ein Buch und klapp den Deckel auf. Wenn man es nun so vor sich liegen hat, dass man es lesen kann, so entspricht der untere Rand der rechten Seite ja der x-Achse, der untere Rand des (hochgeklappten) Deckels der y-Achse und die linke Seite, also die Buchmitte, der z-Achse.
Oder auf die rechte Hand bezoegen: Mittelfinger entspricht x, Daumen y und Zeigefinger z.Soweit richtig?
Und nun drehe das Buch so, dass Du von der anderen Seite diagonal auf den Ursprung kuckst.
Die untere Seite des Buchdeckels zeigt nun nach wie vor nach oben (y), die Buchmitte (z) geht nacht rechts unten und der untere Rand der ersten Seite geht nach links unten (x).
Wenn ich nun wieder meine Hand entsprechend verdrehe (knirscht ein wenig in den Gelenken, aber geht gerade so noch), passen die Finger nach wie vor zu den Buchrändern.Im Bild geht aber x nach rechts unten und z nach links

Verstehst Du jetzt mein Problem?
-
die Auswirkung des Up-Vectors habe ich ohnehin nicht ganz verstanden. In meiner Vorstellung brauche ich nur den Kamerapunkt und den Blickpunkt, wo oben ist, ist dann doch für die Ansicht erstmal uninteressant.
Wenn Du nur die beiden Punkte definierst, hast Du nur eine von 3 Achsen Deines Koordinatensystems - die Kamera duerfte beliebig um ihre Z-Achse rotieren.
Du brauchst also noch einen zusaetzlichen Referenzpunkt um die Ausrichtung Deiner Kamera eindeutig zu definieren.
-
Das hieße also, dass ein Up-Vector (0, 1, 0) in meinem Falle zu einem nicht-othogonalen Koordinatensystem führen würde und ich stattdessen einen Vektor angeben müsste, der ortogonal zu dem Augenvektor steht?
Eher nicht, oder? Denn wenn das so wäre, dann dürfte die Ansicht ja verzerrt sein, was sie aber nicht (nur ein wenig seitenverkehrt
).
-
Dass die Basisvektoren der Matrix orthogonal sind ist schon sehr essenziell und darum regelt das gluLookAt schon intern fuer Dich.
Genauer:
Z= "Target" - "Position"
X= Z x "Up"
Y= X x Z
-
Aaah, das ist sehr gut

Danke, jetzt kapiere ich das wenigstens!
Aber das hat direkt mit meinem Problem trotzdem nichts zu tun, oder? Verdammt, ich tu mir mit der räumlichen Vorstellung schwer, aber mein Buchbeispiel sollte doch dennoch richtig sein.
Was also ist des Rätsels Lösung?
-
das hat direkt mit meinem Problem trotzdem nichts zu tun, oder?
Du hast gar kein Problem.
Schau Dir das right-handed System mal an.
-
Mein Problem ist, dass nach meinem Vorstellungsvermögen es anders aussehen müsste als es tut.
Ich wär schon zufrieden, wenn mir jemand sagen würde, was an meinem Buchdeckel-Beispiel nicht stimmt.

Edit:
Äääh, ich merke gerade, dass ich in meinem Buchbeispiel Zeige- und Mittelfinger vertauscht habe, der Zeigefinger steht natürlich für x und der Mittelfinger für z.
Das nur am Rande, das Verständnisproblem besteht weiterhin.
-
hellihjb schrieb:
Schau Dir das right-handed System mal an.
Moment mal.
Die z-Achse geht in positiver Richtung nach außen???
Hm, ich bin bisher davon ausgegangen, dass sie nach innen geht? Warum heißt das dann Rechte-Hand-Regel? Wenn ich mit den ersten drei Fingern meiner rechten Hand rechte Winkel bilde, dann würden die Achsen nach rechts, oben und innen gehen. Laut Deinem Link entspricht das aber gerade der Linken-Hand-Regel!
Habe ich jetzt ein anatomisches Problem?
Welcher Finger soll für welche Achse stehen? Es tut mir leid, dass ich diese blöden Fragen stellen muss, aber im Moment hängts bei mir total

-
Chewie83 schrieb:
hellihjb schrieb:
Schau Dir das right-handed System mal an.
Moment mal.
Die z-Achse geht in positiver Richtung nach außen???
Hm, ich bin bisher davon ausgegangen, dass sie nach innen geht? Warum heißt das dann Rechte-Hand-Regel? Wenn ich mit den ersten drei Fingern meiner rechten Hand rechte Winkel bilde, dann würden die Achsen nach rechts, oben und innen gehen. Laut Deinem Link entspricht das aber gerade der Linken-Hand-Regel!
Habe ich jetzt ein anatomisches Problem?
Nein, eher ein Problem mit den Augen. Auf der Seite ist es doch genau so dargestellt, wie du es dir vorstellst.
-
Die z-Achse geht in positiver Richtung nach außen???
Wo ist denn in einem Vektorraum "aussen" ?
LH- und RH-System unterscheiden sich - wie Deine beiden Haende - dadurch, dass eine Achse gespiegelt ist.
Wie rum Du's hinstellst is' egal...
-
Oh Mann, endlich hab ich kapiert, wo mein Denkfehler lag.
Bei der Rechte-Hand-Regel werden die Achsen durch Daumen, Zeigefinger und Mittelfinger (genau in dieser Reihenfolge!) realisiert. Ich dachte immer, z geht nach innen (damit meine ich in die Bildfläche, also meinetwegen dem Monitor, hinein).
Aber es ist ja gerade umgekehrt! Damit ist auch klar, warum das Bild richtig ist.
Danke dennoch für Eure Mühen!