Reputation: 443
I try to implement 3D object rotations according data taken from sensor. I have data as quaternions w,x,y,z but to use
glRotatef(xRot,1,0,0);
glRotatef(yRot,0,1,0);
glRotatef(zRot,0,0,1);
I need rotation angles across x,y,z to obtain these with this tutorial and QQuaternion in Qt IDE I write below code:
void quaternion2angle(float w,float x,float y,float z)
{
// Code for quaternion to rotation around axis X Y Z
QQuaternion ql;
ql.setScalar(w);
ql.setX(x);
ql.setY(y);
ql.setZ(z);
if (ql.scalar()>1) ql.normalize();
angle= 2 * acos(ql.scalar());
s= sqrt(1-ql.scalar()*ql.scalar());
if (s<0.001) {
xRot=ql.x();
yRot=ql.y();
zRot=ql.z();
}else
{
xRot=ql.x()/s;
yRot=ql.y()/s;
zRot=ql.y()/s;
}
}
However, when I rotate with above code, movements are not correct, directions are different and also even sensor move 90 degrees to left it move so much little to another direction.
When I search about quaternion and openGL, some gives advice about rotation could be done on camera on openGL by using glMultMatrixf(quaternion.toMatrix)
but I could not convert quaternion to a matrix GLFloat which is requested as parameter in glMultMatrixf. QQuaternion class cloud convert quaternion to QVector4D and gives error variable casting. Maybe the way did is wrong which is below code:
void paintGL()
{
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// adjust camera
glTranslatef(0.0f, 0.0f, -8.0f);
glMultMatrixf(quMatrix.constData());
glRotatef(90,0,1,0);
// no need below
//glRotatef(xRot,1,0,0);
//glRotatef(yRot,0,1,0);
//glRotatef(zRot,0,0,1);
obj.Draw();
glDisable(GL_DEPTH_TEST);
}
void setquMatrix(QVector4D qvec)
{
// read data w,x,y,z
qvec=quaternionRotation(w,x,y,z);
quMatrix=qvec;
}
// Using quaternion and glMultMatrixf
QVector4D quaternionRotation(float w,float x,float y,float z)
{
QQuaternion qlm;
qlm.setScalar(w);
qlm.setX(x);
qlm.setY(y);
qlm.setZ(z);
qlm.normalize();
return qlm.toVector4D();
}
// after taking value above I set matrix which is multiplied with glMultMatrixf
To sum, how can i solve the issue with these quaternions for interpreting rotations on an object with openGL ?
Upvotes: 3
Views: 9068
Reputation: 443
I try out some other methods for implementation.I directly convert quaternions to X Y Z axis angles. I hope it will be useful for others also:
float q0 = q0Buffer.at(i);
float q1 = q1Buffer.at(i);
float q2 = q2Buffer.at(i);
float q3 = q3Buffer.at(i);
float angle_rad = acos(q0) * 2;
float angle_deg = angle_rad * 180 / PI;
float x = q1 / sin(angle_rad/2);
float y = q2 / sin(angle_rad/2);
float z = q3 / sin(angle_rad/2);
Upvotes: 1
Reputation: 48216
You shouldn't convert to axis angle, instead create the rotation matrix directly and use glMultMatrix.
converting a quaternion to matrix can be done with the following: (sourced from my previous code)
inline QMatrix4x4 quatToMat(QQuaternion q)
{
//based on algorithm on wikipedia
// http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion
float w = q.scalar ();
float x = q.x();
float y = q.y();
float z = q.z();
float n = q.lengthSquared();
float s = n == 0? 0 : 2 / n;
float wx = s * w * x, wy = s * w * y, wz = s * w * z;
float xx = s * x * x, xy = s * x * y, xz = s * x * z;
float yy = s * y * y, yz = s * y * z, zz = s * z * z;
float m[16] = { 1 - (yy + zz), xy + wz , xz - wy ,0,
xy - wz , 1 - (xx + zz), yz + wx ,0,
xz + wy , yz - wx , 1 - (xx + yy),0,
0 , 0 , 0 ,1 };
QMatrix4x4 result = QMatrix4x4(m,4,4);
result.optimize ();
return result;
}
You can then use the constData member to pass into multMatrix:
QMatrix4x4 rotation = quatToMat(quat);
glMultMatrix(rotation.constData());
Upvotes: 1