Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Problems with QQuaternion



  • Hello everyboy,

    i want to rotate my object via gui-arows and quaternions. With up and down arrow it should be possible to rotate round the x-axis. with left and right round y and with two other buttons round the z axis.

    I am using opengl in qt. I have achived to rotate the object round every axis via these slot-functions:
    @
    void OpenGLScene::rotate_plus_x()
    {
    OpenGLScene::anglex += 5;
    test->rotation = QQuaternion::fromAxisAndAngle(QVector3D(1,0,0),OpenGLScene::anglex);
    update();

    }

    void OpenGLScene::rotate_minus_x()
    {
    OpenGLScene::anglex -= 5;
    test->rotation = QQuaternion::fromAxisAndAngle(QVector3D(1,0,0),OpenGLScene::anglex);
    update();
    }

    void OpenGLScene::rotate_plus_y()
    {
    OpenGLScene::angley += 5;
    test->rotation = QQuaternion::fromAxisAndAngle(QVector3D(0,1,0),OpenGLScene::angley);
    update();
    }
    @

    In this class my actual rotation is happening.(Where the rotation is multiplied with the modelview matrix)

    @
    QMatrix4x4 matrix;
    matrix.rotate(rotation);
    glMatrixMode (GL_MODELVIEW);
    glLoadIdentity ();

                glPushMatrix();
                light->drawLight(light->light_rotate_x,light->light_rotate_y,light->light_rotate_z);
    
                gluLookAt(   0,   0, -400,  
                             0,   0,    0,   
                             0,   1,    0);  
                qMultMatrix(matrix);
                object->drawObject(Red,Green,Blue);
                draw->drawAxes();
                glPopMatrix();
    

    @

    (The qmultmatrix function is from the pbuffers-example from the qt-examples.)

    My problem is, that the object is always jumping back to the initial position, when i change the rotation-axis. For instance, when i rotate round the x-axis and afterwards round the y-axis the object starts to rotate from the initial position and not from the newest one.

    I think there might be a problem with how i multiply my matrix with the modelview-matrix. I think i should store the last changed matrix and multiply it with the newest one. How to do that is a mystery to me.
    I have tried several things but nothing is working.

    Maybe you could help me.

    Thanks in Advance



  • You need to do the math. You create a unit matrix and then rotate it according to a certain quaternion -- that is, you're throwing away the previous rotation by assigning them in your slots.

    IIRC the following should provide better results:
    @
    void OpenGLScene::rotate_plus_x()
    {
    OpenGLScene::anglex += 5;
    test->rotation *= QQuaternion::fromAxisAndAngle(QVector3D(1,0,0),OpenGLScene::anglex);
    update();

    }

    void OpenGLScene::rotate_minus_x()
    {
    OpenGLScene::anglex -= 5;
    test->rotation *= QQuaternion::fromAxisAndAngle(QVector3D(1,0,0),OpenGLScene::anglex);
    update();
    }

    void OpenGLScene::rotate_plus_y()
    {
    OpenGLScene::angley += 5;
    test->rotation *= QQuaternion::fromAxisAndAngle(QVector3D(0,1,0),OpenGLScene::angley);
    update();
    }
    @



  • As FranzK says you are resetting your rotation matrices in the rotate_*() functions. Instead of replacing the matrix, calculate another matrix from the quarternion and pre-multiply the pre-existing transformation matrix with it.

    I think the order of the matrix multiplication should be opposite to what Franzk said though (but to be fair I've not tried it myself). For e.g.:

    @
    void OpenGLScene::rotate_plus_x()
    {
    OpenGLScene::anglex += 5;
    QMatrix4x4 newRotation = QQuaternion::fromAxisAndAngle(QVector3D(1,0,0),OpenGLScene::anglex);
    test->rotation = newRotation * test->rotation;
    update();
    }
    @



  • Gah! Sorry ignore my last post I was thinking of matrices not quaternions. Sorry for the confusion. Long day ;-)



  • Thanks to both of you. Especially to FranzK. It was exactly the problem.
    Now its working. One thing was wrong as well.
    It should be:

    @
    OpenGLScene::anglex = 5;
    @
    or
    @
    OpenGLScene::anglex = -5;
    @

    Otherwise the rotationangle gets bigger and bigger with every click.
    For those who are interested.


Log in to reply