karligula
07-14-2008, 05:50 AM
Hello folks,
I'm using a quaternion to define an entity's orientation, but I want to keep it flat to the world, so I want to zero the roll. I've written this bit of code:
quaternion orientation;
entity->GetOrientation(&orientation);
// Get the x and z axes
vec3 xAxis;
vec3 zAxis;
mtx matrix;
quaternionToMatrix(&matrix,&orientation);
xAxis.x=matrix.f[0][0];
xAxis.y=matrix.f[0][1];
xAxis.z=matrix.f[0][2];
zAxis.x=matrix.f[2][0];
zAxis.y=matrix.f[2][1];
zAxis.z=matrix.f[2][2];
// Get the flat axis
vec3 flatAxis;
if((zAxis.y<0.99999f)&&(zAxis.y>-0.99999f))
{
// Create a flat axis from the cross product of the z axis and a vertical vector
vec3 vertical;
vertical.x=0.0f;
vertical.y=1.0f;
vertical.z=0.0f;
veccross(&flatAxis,&vertical,&zAxis);
vecnormalise(&flatAxis,&flatAxis);
}
else
{
// If the zaxis is pointing straight up or down, getting a flat axis with a cross product won't work
// so set a default flat axis along the x axis
flatAxis.x=1.0f;
flatAxis.y=0.0f;
flatAxis.z=0.0f;
}
// Get the current roll angle between the xaxis and the flat axis
float rollAngle=RAD2DEG(acos(vecdot(&xAxis,&flatAxis)));
// Get the rotation angle
float angle=-rollAngle;
// Get the rotation axis
vec3 axis;
axis.x=0.0f;
axis.y=0.0f;
axis.z=1.0f;
// Create a rotation quat from the rotation axis and angle, and apply it to the orientation
quaternion rotation;
axisAngleToQuaternion(&rotation,&axis,DEG2RAD(angle));
quaternionMul(&orientation,&orientation,&rotation);
quaternionNormalise(&orientation);
// Set the orientation
entity->SetOrientation(&orientation);
But for the life of me I CANNOT get it to work. Despite applying the opposite rotation, the orientation actually increases in the same direction, ie angle 0f 7 degrees becomes 14 then 28, etc. So the quat just seems to spin around its z axis and never goes flat.
All the functions I'm calling here are used many times elsewhere in the engine so I'm pretty sure they're working fine. I've checked and double checked and triple checked the order of the parameters I'm passing. Is there some subtely to quats that I'm not taking into account?
I'm getting ready to throw the PC out the window here...
I'm using a quaternion to define an entity's orientation, but I want to keep it flat to the world, so I want to zero the roll. I've written this bit of code:
quaternion orientation;
entity->GetOrientation(&orientation);
// Get the x and z axes
vec3 xAxis;
vec3 zAxis;
mtx matrix;
quaternionToMatrix(&matrix,&orientation);
xAxis.x=matrix.f[0][0];
xAxis.y=matrix.f[0][1];
xAxis.z=matrix.f[0][2];
zAxis.x=matrix.f[2][0];
zAxis.y=matrix.f[2][1];
zAxis.z=matrix.f[2][2];
// Get the flat axis
vec3 flatAxis;
if((zAxis.y<0.99999f)&&(zAxis.y>-0.99999f))
{
// Create a flat axis from the cross product of the z axis and a vertical vector
vec3 vertical;
vertical.x=0.0f;
vertical.y=1.0f;
vertical.z=0.0f;
veccross(&flatAxis,&vertical,&zAxis);
vecnormalise(&flatAxis,&flatAxis);
}
else
{
// If the zaxis is pointing straight up or down, getting a flat axis with a cross product won't work
// so set a default flat axis along the x axis
flatAxis.x=1.0f;
flatAxis.y=0.0f;
flatAxis.z=0.0f;
}
// Get the current roll angle between the xaxis and the flat axis
float rollAngle=RAD2DEG(acos(vecdot(&xAxis,&flatAxis)));
// Get the rotation angle
float angle=-rollAngle;
// Get the rotation axis
vec3 axis;
axis.x=0.0f;
axis.y=0.0f;
axis.z=1.0f;
// Create a rotation quat from the rotation axis and angle, and apply it to the orientation
quaternion rotation;
axisAngleToQuaternion(&rotation,&axis,DEG2RAD(angle));
quaternionMul(&orientation,&orientation,&rotation);
quaternionNormalise(&orientation);
// Set the orientation
entity->SetOrientation(&orientation);
But for the life of me I CANNOT get it to work. Despite applying the opposite rotation, the orientation actually increases in the same direction, ie angle 0f 7 degrees becomes 14 then 28, etc. So the quat just seems to spin around its z axis and never goes flat.
All the functions I'm calling here are used many times elsewhere in the engine so I'm pretty sure they're working fine. I've checked and double checked and triple checked the order of the parameters I'm passing. Is there some subtely to quats that I'm not taking into account?
I'm getting ready to throw the PC out the window here...