# Translating from a quaternion?

OK hello everyone again.

You may or may not know that I have been struggling with a quaternion rotation system in my 3D OpenGL game written in C.

I managed to work it out (with the help of a few helpful developers) but I have now another problem: how to translate.

I was told to ‘find the z vector from the matrix’ and translate along that but that doesn’t work.

How do I work out a set of coordinates to translate to when I have a rotation matrix and quaternion?

P.S.

``````
shipRotation.z = pitch   * DEG_TO_RAD ;
shipRotation.y = heading  * DEG_TO_RAD ;
shipRotation.x = roll * DEG_TO_RAD;

q1 =  eulerToQuat(shipRotation);

q2 = quatMult(q1,q2);
shipMatrix = quatToMatrix(q2);

glMultMatrixf(  shipMatrix.m );

``````

The components m[3,0], m[3,1] and m[3,2] are the traslation x, y and z. Simply set them before using the matrix in glMultMatrixf

Hmmm. I don’t think I explained my problem. I don’t have a specific x,y and z values, but an airspeed variable. I want my ship to travel along the Z axis (locally, like an aeroplane).

I could use things like sin(pitch) but I’m not sure about these and quaternions.
Here’s my current code:

``````	translation.x +=  shipMatrix.m[8];
translation.y +=  shipMatrix.m[9];
translation.z +=  shipMatrix.m[10];

xp = translation.x * airspeed ;
yp = translation.y * airspeed ;
zp = translation.z * airspeed ;

glTranslatef(-xp ,-yp,zp);

``````

I was told in my other thread to:

translate along the Z vector of the matrix, that is matrix[8] matrix[9] and matrix[10].

But my code acts strangely.

So, you need the “forward” vector that a Mat3x3 has.

``````
struct Mat3{
vec3 GetForwardVector(){
return vec3(a20,a21,a22);
}

union {
struct {
float a00, a10, a20;
float a01, a11, a21;
float a02, a12, a22;
};

float mat_array[9];
};
};

``````

You have this:

``````

struct MyObject{
Quaternion Q;
vec3 position;

float speed;
...

void update();
};

void MyObject::update(){
Mat3 rotation = Q.toMatrix3();
vec3 forwardVector = rotation.GetForwardVector();
position += speed*forwardVector;
}

``````

Sorry to seem stupid but I only know C and I’m not really sure what the code does. My matrix is stored in the struct like this:

``````
typedef struct
{
float m[16];
}matrix;

``````

But if I change my code to this:

``````	shipRotation.z = pitch   * DEG_TO_RAD ;
shipRotation.y = heading  * DEG_TO_RAD ;
shipRotation.x = roll * DEG_TO_RAD;

q1 =  eulerToQuat(shipRotation);

q2 = quatMult(q1,q2);

translation.x +=  shipMatrix.m[12];
translation.y +=  shipMatrix.m[13];
translation.z +=  shipMatrix.m[14];

xp += translation.x * airspeed ;
yp += translation.y * airspeed ;
zp += translation.z * airspeed ;

glTranslatef(xp ,yp,zp);

``````

Nothing happens. I can still rotate fine but no translation.

This code:

``````
translation.x +=  shipMatrix.m[12];
translation.y +=  shipMatrix.m[13];
translation.z +=  shipMatrix.m[14];

``````

shouldn’t be?..

``````
translation.x =  shipMatrix.m[12];
translation.y =  shipMatrix.m[13];
translation.z =  shipMatrix.m[14];

``````

I tried that but still nothing happens.

Anyone?

I already wrote what I think you should code; I use very similar code successfully.

Well it doesn’t seem to work for me. Here’s my exact code:

``````

shipRotation.z = pitch   * DEG_TO_RAD ;
shipRotation.y = heading  * DEG_TO_RAD ;
shipRotation.x = roll * DEG_TO_RAD;

q1 =  eulerToQuat(shipRotation);

q2 = quatMult(q1,q2);

//glTranslatef(0.0f,0.0f,airspeed );

//q1 = eulerToQuat(shipRotation);
//quatMultiply(q1, q2, q2);

//q2.w = 1.0;
shipMatrix = quatToMatrix(q2);

glLoadMatrixf(  shipMatrix.m );

translation.z =  shipMatrix.m[8];
translation.y =  shipMatrix.m[9];
translation.x =  shipMatrix.m[10];

xp +=  airspeed * translation.z;
yp += airspeed * translation.y;
zp +=   airspeed * translation.x;

glTranslatef(xp ,yp,zp);

drawWorld();

``````

And all of the quaternion functions:

``````quaternion eulerToQuat(vec3D euler)
{
quaternion quat;
float sinAngle;
float angle;

vec3D axis;

float c1 = cos((euler.y* DEG_TO_RAD) / 2);
float c2 = cos((euler.x* DEG_TO_RAD) / 2);
float c3 = cos((euler.z* DEG_TO_RAD) / 2);
float s1 = sin((euler.y* DEG_TO_RAD) / 2);
float s2 = sin((euler.x* DEG_TO_RAD) / 2);
float s3 = sin((euler.z* DEG_TO_RAD) / 2);

quat.w = (c1 * c2 *  c3 - s1 *  s2 *  s3);
quat.x = (s1 *  s2 *  c3 +c1 *  c2 *  s3);
quat.y = (s1  * c2  * c3 + c1 *  s2 *  s3);
quat.z = (c1 *  s2 *  c3 - s1 *  c2 *  s3);

return quat;
}

quaternion axisAngleToQuat(vec3D axis, float angle)
{
quaternion quat;
float sinAngle;

angle *= 0.5f;
axis = normVec3D(axis);
sinAngle = sin(angle);
quat.x = (axis.x * sinAngle);
quat.y = (axis.y * sinAngle);
quat.z = (axis.z * sinAngle);
quat.w = cos(angle);

return quat;

}

quaternion conjugateQuat(quaternion quat)
{
quaternion ans;

ans.x = -quat.x;
ans.y = -quat.y;
ans.z = -quat.z;

return ans;
}

quaternion quatMult(quaternion  quat1, quaternion quat2)
{
vec3D vector1, vector2, cross;
quaternion quat3;
float angle;

vector1.x = quat1.x;
vector1.y = quat1.y;
vector1.z = quat1.z;
vector2.x = quat2.x;
vector2.y = quat2.y;
vector2.z = quat2.z;
angle = (quat1.w * quat2.w) - dotprodVec3D(vector1, vector2);

cross = crossprodVec3D(vector1, vector2);
vector1.x *= quat2.w;
vector1.y *= quat2.w;
vector1.z *= quat2.w;
vector2.x *= quat1.w;
vector2.y *= quat1.w;
vector2.z *= quat1.w;

quat3.x = vector1.x + vector2.x + cross.x;
quat3.y = vector1.y + vector2.y + cross.y;
quat3.z = vector1.z + vector2.z + cross.z;
quat3.w = angle;

return quat3;
}

matrix quatToMatrix(quaternion quat) {
matrix qmatrix;

qmatrix.m[0]  = (1.0f - (2.0f * ((quat.y * quat.y) + (quat.z * quat.z))));
qmatrix.m[1]  =         (2.0f * ((quat.x * quat.y) + (quat.z * quat.w)));
qmatrix.m[2]  =         (2.0f * ((quat.x * quat.z) - (quat.y * quat.w)));
qmatrix.m[3]  = 0.0f;
qmatrix.m[4]  =         (2.0f * ((quat.x * quat.y) - (quat.z * quat.w)));
qmatrix.m[5]  = (1.0f - (2.0f * ((quat.x * quat.x) + (quat.z * quat.z))));
qmatrix.m[6]  =         (2.0f * ((quat.y * quat.z) + (quat.x * quat.w)));
qmatrix.m[7]  = 0.0f;
qmatrix.m[8]  =         (2.0f * ((quat.x * quat.z) + (quat.y * quat.w)));
qmatrix.m[9]  =         (2.0f * ((quat.y * quat.z) - (quat.x * quat.w)));
qmatrix.m[10] = (1.0f - (2.0f * ((quat.x * quat.x) + (quat.y * quat.y))));
qmatrix.m[11] = 0.0f;
qmatrix.m[12] = 0.0f;
qmatrix.m[13] = 0.0f;
qmatrix.m[14] = 0.0f;
qmatrix.m[15] = 1.0f;

return qmatrix;
}

``````

AHA! I think the problem is that your matrices are row major whereas opengl matrices are column major. So I should be using 8,9,10 (My matrices are 4x4) but still something is wrong.

However if we look at NeHe’s code:

``````	GLfloat Matrix[16];

glRotatef(m_HeadingDegrees, 0.0f, 1.0f, 0.0f);
glRotatef(m_PitchDegrees, 1.0f, 0.0f, 0.0f);

glGetFloatv(GL_MODELVIEW_MATRIX, Matrix);

m_DirectionVector.i = Matrix[8];
m_DirectionVector.k = Matrix[10];

glLoadIdentity();

glRotatef(m_PitchDegrees, 1.0f, 0.0f, 0.0f);

glGetFloatv(GL_MODELVIEW_MATRIX, Matrix);
m_DirectionVector.j = Matrix[9];

glRotatef(m_HeadingDegrees, 0.0f, 1.0f, 0.0f);

// Scale the direction by our speed.
m_DirectionVector *= m_ForwardVelocity;

// Increment our position by the vector
m_Position.x += m_DirectionVector.i;
m_Position.y += m_DirectionVector.j;
m_Position.z += m_DirectionVector.k;

// Translate to our new position.
glTranslatef(-m_Position.x, -m_Position.y, m_Position.z);
``````

He seems to get the 9 element of the matrix before he changes the matrix…