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();
}
@ -
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.