ProgrammingPlumber

01-23-2016, 11:59 AM

Hi everyone.

I know that gluLookAt is handy for using it from another object's perspective to look at you and then copying that matrix, inverting it, and using it to multiply against the GL_MODELVIEW matrix to make an object track you, but doing it this way makes it rotate toward you instantly, which is fine for a FPS game where the enemy just needs to turn and look at you. But this isn't ideal for a drone ship in space flying around in 3D that needs to rotate at it's own limited maximum rotate speed and slowly turn toward you in a smooth and realistic manner.

I tried the code on a few sites which teach how to convert a rotation matrix to a quaternion so that I can use the quaternion instead of the inverted gluLookAt matrix copy to do the orientation but it's not duplicating what the inverted matrix does. The code is identical on two different sites that I checked so it "supposedly" has to be right. My gut feeling is that I'm either making an assumption that those sites didn't explain, or that by some fluke, those formulas work for DirectX or some other GL other than OpenGL.

Has anyone here been able to create a rotation quaternion from a rotation matrix that duplicates what the matrix does perfectly? If so, would you be kind enough to show me the code that you use to get it to work? This is what I'm using now: The rmq_x, rmq_y, rmq_z, rmq_w variables are global GLfloat variables because the function can't return an array or multiple values. I pass it the rotation matrix that I inverted from the gluLookAt matrix to try and create the quaternion:

void Ship::rotationMatrixToQuaternion(GLfloat inp_mat[16])

{

GLfloat t = 1 + inp_mat[0] + inp_mat[5] + inp_mat[10];

GLfloat s = 0.0;

if (t > 0.0)

{

s = sqrt(t) * 2;

rmq_x = (inp_mat[6] - inp_mat[9]) / s;

rmq_y = (inp_mat[8] - inp_mat[2]) / s;

rmq_z = (inp_mat[1] - inp_mat[4]) / s;

rmq_w = 0.25 * s;

}

else if ((inp_mat[0] > inp_mat[5]) && (inp_mat[0] > inp_mat[10]))

{

s = sqrt(1.0 + inp_mat[0] - inp_mat[5] - inp_mat[10]) * 2;

rmq_x = 0.25 * s;

rmq_y = (inp_mat[1] + inp_mat[4] ) / s;

rmq_z = (inp_mat[8] + inp_mat[2] ) / s;

rmq_w = (inp_mat[6] - inp_mat[9] ) / s;

}

else if (inp_mat[5] > inp_mat[10])

{

s = sqrt(1.0 + inp_mat[5] - inp_mat[0] - inp_mat[10]) * 2;

rmq_x = (inp_mat[1] + inp_mat[4]) / s;

rmq_y = 0.25 * s;

rmq_z = (inp_mat[6] + inp_mat[9]) / s;

rmq_w = (inp_mat[8] - inp_mat[2]) / s;

}

else

{

s = sqrt(1.0 + inp_mat[10] - inp_mat[0] - inp_mat[5]) * 2;

rmq_x = (inp_mat[8] + inp_mat[2]) / s;

rmq_y = (inp_mat[6] + inp_mat[9]) / s;

rmq_z = 0.25 * s;

rmq_w = (inp_mat[1] - inp_mat[4]) / s;

}

}

Any help anyone can give me would be very much appreciated.

I know that gluLookAt is handy for using it from another object's perspective to look at you and then copying that matrix, inverting it, and using it to multiply against the GL_MODELVIEW matrix to make an object track you, but doing it this way makes it rotate toward you instantly, which is fine for a FPS game where the enemy just needs to turn and look at you. But this isn't ideal for a drone ship in space flying around in 3D that needs to rotate at it's own limited maximum rotate speed and slowly turn toward you in a smooth and realistic manner.

I tried the code on a few sites which teach how to convert a rotation matrix to a quaternion so that I can use the quaternion instead of the inverted gluLookAt matrix copy to do the orientation but it's not duplicating what the inverted matrix does. The code is identical on two different sites that I checked so it "supposedly" has to be right. My gut feeling is that I'm either making an assumption that those sites didn't explain, or that by some fluke, those formulas work for DirectX or some other GL other than OpenGL.

Has anyone here been able to create a rotation quaternion from a rotation matrix that duplicates what the matrix does perfectly? If so, would you be kind enough to show me the code that you use to get it to work? This is what I'm using now: The rmq_x, rmq_y, rmq_z, rmq_w variables are global GLfloat variables because the function can't return an array or multiple values. I pass it the rotation matrix that I inverted from the gluLookAt matrix to try and create the quaternion:

void Ship::rotationMatrixToQuaternion(GLfloat inp_mat[16])

{

GLfloat t = 1 + inp_mat[0] + inp_mat[5] + inp_mat[10];

GLfloat s = 0.0;

if (t > 0.0)

{

s = sqrt(t) * 2;

rmq_x = (inp_mat[6] - inp_mat[9]) / s;

rmq_y = (inp_mat[8] - inp_mat[2]) / s;

rmq_z = (inp_mat[1] - inp_mat[4]) / s;

rmq_w = 0.25 * s;

}

else if ((inp_mat[0] > inp_mat[5]) && (inp_mat[0] > inp_mat[10]))

{

s = sqrt(1.0 + inp_mat[0] - inp_mat[5] - inp_mat[10]) * 2;

rmq_x = 0.25 * s;

rmq_y = (inp_mat[1] + inp_mat[4] ) / s;

rmq_z = (inp_mat[8] + inp_mat[2] ) / s;

rmq_w = (inp_mat[6] - inp_mat[9] ) / s;

}

else if (inp_mat[5] > inp_mat[10])

{

s = sqrt(1.0 + inp_mat[5] - inp_mat[0] - inp_mat[10]) * 2;

rmq_x = (inp_mat[1] + inp_mat[4]) / s;

rmq_y = 0.25 * s;

rmq_z = (inp_mat[6] + inp_mat[9]) / s;

rmq_w = (inp_mat[8] - inp_mat[2]) / s;

}

else

{

s = sqrt(1.0 + inp_mat[10] - inp_mat[0] - inp_mat[5]) * 2;

rmq_x = (inp_mat[8] + inp_mat[2]) / s;

rmq_y = (inp_mat[6] + inp_mat[9]) / s;

rmq_z = 0.25 * s;

rmq_w = (inp_mat[1] - inp_mat[4]) / s;

}

}

Any help anyone can give me would be very much appreciated.