Objekt um eigene Achse rotieren

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Audience
Beiträge: 6
Registriert: 20.09.2009, 13:33

Objekt um eigene Achse rotieren

Beitrag von Audience »

Hallo,

ich möchte ein Objekt immer um die eigene Achse drehen, also diese bei jedem Schritt auch mitrotieren.
Meine Idee ist folgende: Die gedrehten Koordinatenachsen des Objektes stehen ja in meiner MODELVIEW Matrix und zwar in der ersten Spalte die x-Achse, in der zweiten die y-Achse und in der dritten die z-Achse.

Code: Alles auswählen

    glLoadIdentity( );   
    glTranslatef(-1.8f, 0.0f, -12.0f);
    glRotatef(30.0f, 1.0f, 0.0f, 0.0f); //Um die normale X-Achse drehen (weil ja globale und lokale Objektachse übereinstimmen)
    glGetFloatv(GL_MODELVIEW_MATRIX , modelview); //Modelview-Matrix holen
    glRotatef(30.0f, modelview[4], modelview[5], modelview[6]); //Um die gedrehte Y-Achse des Objektes rotieren
    glGetFloatv(GL_MODELVIEW_MATRIX , modelview);
    glRotatef(30.0f, modelview[2], modelview[6], modelview[10]); //Und jetzt noch um die gedrehte Z-Achse drehen

    //Würfel zeichnen
    glBegin( GL_QUADS );                 /* Draw A Quad                      */
      glColor3f(   0.0f,  1.0f,  0.0f ); /* Set The Color To Green           */
      glVertex3f(  1.0f,  1.0f, -1.0f ); /* Top Right Of The Quad (Top)      */
      glVertex3f( -1.0f,  1.0f, -1.0f ); /* Top Left Of The Quad (Top)       */
      glVertex3f( -1.0f,  1.0f,  1.0f ); /* Bottom Left Of The Quad (Top)    */
      glVertex3f(  1.0f,  1.0f,  1.0f ); /* Bottom Right Of The Quad (Top)   */

      glColor3f(   1.0f,  0.5f,  0.0f ); /* Set The Color To Orange          */
      glVertex3f(  1.0f, -1.0f,  1.0f ); /* Top Right Of The Quad (Botm)     */
      glVertex3f( -1.0f, -1.0f,  1.0f ); /* Top Left Of The Quad (Botm)      */
      glVertex3f( -1.0f, -1.0f, -1.0f ); /* Bottom Left Of The Quad (Botm)   */
      glVertex3f(  1.0f, -1.0f, -1.0f ); /* Bottom Right Of The Quad (Botm)  */

      glColor3f(   1.0f,  0.0f,  0.0f ); /* Set The Color To Red             */
      glVertex3f(  1.0f,  1.0f,  1.0f ); /* Top Right Of The Quad (Front)    */
      glVertex3f( -1.0f,  1.0f,  1.0f ); /* Top Left Of The Quad (Front)     */
      glVertex3f( -1.0f, -1.0f,  1.0f ); /* Bottom Left Of The Quad (Front)  */
      glVertex3f(  1.0f, -1.0f,  1.0f ); /* Bottom Right Of The Quad (Front) */

      glColor3f(   1.0f,  1.0f,  0.0f ); /* Set The Color To Yellow          */
      glVertex3f(  1.0f, -1.0f, -1.0f ); /* Bottom Left Of The Quad (Back)   */
      glVertex3f( -1.0f, -1.0f, -1.0f ); /* Bottom Right Of The Quad (Back)  */
      glVertex3f( -1.0f,  1.0f, -1.0f ); /* Top Right Of The Quad (Back)     */
      glVertex3f(  1.0f,  1.0f, -1.0f ); /* Top Left Of The Quad (Back)      */

      glColor3f(   0.0f,  0.0f,  1.0f ); /* Set The Color To Blue            */
      glVertex3f( -1.0f,  1.0f,  1.0f ); /* Top Right Of The Quad (Left)     */
      glVertex3f( -1.0f,  1.0f, -1.0f ); /* Top Left Of The Quad (Left)      */
      glVertex3f( -1.0f, -1.0f, -1.0f ); /* Bottom Left Of The Quad (Left)   */
      glVertex3f( -1.0f, -1.0f,  1.0f ); /* Bottom Right Of The Quad (Left)  */

      glColor3f(   1.0f,  0.0f,  1.0f ); /* Set The Color To Violet          */
      glVertex3f(  1.0f,  1.0f, -1.0f ); /* Top Right Of The Quad (Right)    */
      glVertex3f(  1.0f,  1.0f,  1.0f ); /* Top Left Of The Quad (Right)     */
      glVertex3f(  1.0f, -1.0f,  1.0f ); /* Bottom Left Of The Quad (Right)  */
      glVertex3f(  1.0f, -1.0f, -1.0f ); /* Bottom Right Of The Quad (Right) */
    glEnd( );                            /* Done Drawing The Quad            */
Irgendwie tut das Ganze aber nicht, obwohl ich mir mit meiner Idee ziemlich sicher bin, dass sie funktioniert. Habe ich irgendwo einen Denkfehler gemacht?
Ich habe mich an diesem Tutorial orientiert: http://wiki.delphigl.com/index.php/Tuto ... hse_drehen

Gruß,
Audience
Stefan Zerbst
Moderator
Beiträge: 189
Registriert: 25.02.2009, 20:54

Re: Objekt um eigene Achse rotieren

Beitrag von Stefan Zerbst »

Hi,

man könnte sich die Achsen auch merken und diese Rotieren, dazu muss man sich nicht die MODELVIEW Matrix auslesen. Aber im Prinzip ist das so korrekt. Allerdings darf man erst am Ende translieren, da die Translation die Punkte erst verschiebt. Wenn man danach erst rotiert dann werden die verschobenen Punkte rotiert und das führt zu einem anderen Ergebnis als erwartet.

Ciao,
Stefan
Audience
Beiträge: 6
Registriert: 20.09.2009, 13:33

Re: Objekt um eigene Achse rotieren

Beitrag von Audience »

Ja, wenn ich aber danach translatiere dann bewegt sich das Objekt um die Objektachse im Translationsabstand. Die Reihenfolge ist schon so korrekt (wie im Tutorial auch).Wenn ich die Translation ausschalte dann dreht sich mein Würfel immer noch nicht korrekt ...
Soll ich mal mein gesamtes Testprogramm posten?
Benutzeravatar
Zudomon
Establishment
Beiträge: 2139
Registriert: 25.03.2009, 08:20
Kontaktdaten:

Re: Objekt um eigene Achse rotieren

Beitrag von Zudomon »

M = Modelviewmatrix
P = Translation von M
M' = M * Translationsmatix(-P) * RotationsmatrixUmEineAchse(Achse, Winkel) * Translationsmatrix(P)
joeydee
Establishment
Beiträge: 724
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: Objekt um eigene Achse rotieren

Beitrag von joeydee »

Wie kommst du auf 2/6/10 für z? Sollte 8/9/10 sein.

Wenn die Translation Probleme macht (also auf welcher Achse am Ende verschoben wird): lies 12/13/14 aus, das ist die aktuelle Position, und schreib sie am Ende wieder unverändert rein.


Aber warum so kompliziert? Ich habe mich vor Jahren mal damit beschäftigt, folgende Notiz fand ich gerade bei mir: "Eine Transformation findet in OpenGL immer im aktuellen Modell-Koordinatensystem statt."
Ich hoffe das trifft noch zu - hier mal ein Snippet aus meinem alten Code. Aber fragt mich nicht warum ich double und float gemischt habe, war wohl die Ungeduld ;-) Namensgebung hält sich auch an keine Standards - bitte um Verzeihung...

Code: Alles auswählen

// Bewegen des Modells
void glModellsystem::Bewegen(float Pitch, float Roll, float Heading, float Speed)
{
	//aktuelle Matrix sichern
	glPushMatrix();
		//Systemmatrix in OpenGL laden und ändern
		glLoadMatrixd (Systemmatrix);
		glRotatef (Pitch, 1, 0, 0); 
		glRotatef (Roll, 0, 0, 1);
		glRotatef (-Heading, 0, 1, 0);
		glTranslatef (0, 0, Speed);
		//Systemmatrix ins Array zurücklesen
		glGetDoublev (GL_MODELVIEW_MATRIX, Systemmatrix);
	//alte Matrix wiederherstellen
	glPopMatrix();

}

//Modell zeichnen
void glModellsystem::Zeichnen(int ListenNummer)
{
	glPushMatrix();
	glMultMatrixd (Systemmatrix);
	//Zeichnen des Modells, falls eine ListenNummer übergeben
	if(ListenNummer>-1){
		glCallList (ListenNummer);
		}
	glPopMatrix();
}

Ich hab praktisch die Matrix für weitere Zwecke immer mit dem Modell gespeichert und beim Rendern einfach in die OGL-Renderkette multipliziert. Bewegen und Rendern sind damit auch völlig unabhängig voneinander.

Übrigens: probier mal aus was passiert bei glRotatef(1,pitch,yaw,roll) statt die Achsen einzeln aufzurufen - funktioniert für diesen Zweck gerade in einer anderen Engine wunderbar, die von der Beschreibung her dieselbe Achsenrotations-Funktion wie OGL haben müsste, aber den mathematischen Beweis werd ich dir schuldig bleiben.
Audience
Beiträge: 6
Registriert: 20.09.2009, 13:33

Re: Objekt um eigene Achse rotieren

Beitrag von Audience »

@joeydee: Deine Lösung in Ehren, aber du hast dich wieder abhängig von der Reihenfolge de glRotate() Aufrufe gemacht.
Im OpenGL FAQ steht folgendes:
9.162 How can I transform an object with a given yaw, pitch, and roll?

The upper left 3x3 portion of a transformation matrix is composed of the new X, Y, and Z axes of the post-transformation coordinate space.

If the new transform is a roll, compute new local Y and X axes by rotating them "roll" degrees around the local Z axis. Do similar calculations if the transform is a pitch or yaw. Then simply construct your transformation matrix by inserting the new local X, Y, and Z axes into the upper left 3x3 portion of an identity matrix. This matrix can be passed as a parameter to glMultMatrix().

Further rotations should be computed around the new local axes. This will inevitably require rotation about an arbitrary axis, which can be confusing to inexperienced 3D programmers. This is a basic concept in linear algebra.

Many programmers apply all three transformations -- yaw, pitch, and roll -- at once as successive glRotate() calls about the X, Y, and Z axes. This has the disadvantage of creating gimbal lock, in which the result depends on the order of glRotate() calls.
joeydee
Establishment
Beiträge: 724
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: Objekt um eigene Achse rotieren

Beitrag von joeydee »

Tatsache ist, wenn diese Art der Steuerung für Echtzeit-Navigation gedacht ist, kann man das vernachlässigen, da die Winkel extrem klein sind. Genau dafür war es gedacht und hat sich eigentlich bewährt. Aber du hast wohl was anderes vor, da hab ich was falsches reininterpretiert :-)

Hat mein Tip was gebracht, die Arraywerte 8/9/10 statt 2/6/10 für die Z-Achse zu nehmen?
Antworten