I'm trying to get my camera implemented with a glm::quat used to store the rotation.
However, whenever I do circles with the mouse, the camera rotates along the axis I am viewing (i.e. I think it's called the target axis). For example, if I rotated the mouse in a clockwise fashion, the camera rotates clockwise around the axis.
I initialize my quaternion like so:
void Camera::initialize()
{
orientationQuaternion_ = glm::quat();
orientationQuaternion_ = glm::normalize(orientationQuaternion_);
}
I rotate like so:
void Camera::rotate(const glm::detail::float32& degrees, const glm::vec3& axis)
{
orientationQuaternion_ = orientationQuaternion_ * glm::normalize(glm::angleAxis(degrees, axis));
}
and I set the viewMatrix like so:
void Camera::render()
{
glm::quat temp = glm::conjugate(orientationQuaternion_);
viewMatrix_ = glm::mat4_cast(temp);
viewMatrix_ = glm::translate(viewMatrix_, glm::vec3(-pos_.x, -pos_.y, -pos_.z));
}
The only axis' I actually try to rotate are the X and Y axis (i.e. (1,0,0) and (0,1,0)).
Here is a video of what is going on: Camera weird rotation
Anyone have any idea why I see my camera rotating around the target axis?
EDIT
I added some debug output for the values that are getting calculated.
First entry is the initialized quaternion, calculated with
std::cout << "quat initialized: " << glm::to_string(glm::eulerAngles(orientationQuaternion_)) << std::endl;
Then I output (in the rotate method) the before and after quaternion, and also the rotation. I output them with:
void Camera::rotate(const glm::detail::float32& degrees, const glm::vec3& axis)
{
std::cout << "orientation before: " << glm::to_string( glm::eulerAngles(orientationQuaternion_) ) << std::endl;
orientationQuaternion_ = glm::normalize(orientationQuaternion_) * glm::normalize(glm::angleAxis(degrees, glm::normalize(axis)));
orientationQuaternion_ = glm::normalize(orientationQuaternion_);
std::cout << "rotation: " << glm::to_string( glm::eulerAngles(glm::angleAxis(degrees, axis)) ) << std::endl;
std::cout << "orientation after: " << glm::to_string( glm::eulerAngles(orientationQuaternion_) ) << std::endl;
}
Here's the output data:
quat initialized: fvec3(0.000000, -0.000000, 0.000000)
orientation before: fvec3(0.000000, -0.000000, 0.000000)
rotation: fvec3(-0.363636, -0.000000, 0.000000)
orientation after: fvec3(-0.363636, 0.000000, 0.000000)
orientation before: fvec3(-0.363636, 0.000000, 0.000000)
rotation: fvec3(0.000000, -0.545454, 0.000000)
orientation after: fvec3(-0.363653, -0.545444, 0.003462)
orientation before: fvec3(-0.363653, -0.545444, 0.003462)
rotation: fvec3(-4.909091, -0.000000, 0.000000)
orientation after: fvec3(-5.272744, -0.545443, 0.003462)
orientation before: fvec3(-5.272744, -0.545443, 0.003462)
rotation: fvec3(0.000000, 5.272728, 0.000000)
orientation after: fvec3(-5.290381, 4.704929, -0.482044)
orientation before: fvec3(-5.290381, 4.704929, -0.482044)
rotation: fvec3(13.272726, -0.000000, 0.000000)
orientation after: fvec3(7.982345, 4.704931, -0.482044)
orientation before: fvec3(7.982345, 4.704931, -0.482044)
rotation: fvec3(0.000000, 6.909091, 0.000000)
orientation after: fvec3(8.120677, 11.546086, 0.494900)
orientation before: fvec3(8.120677, 11.546086, 0.494900)
rotation: fvec3(7.636363, -0.000000, 0.000000)
orientation after: fvec3(15.757041, 11.546085, 0.494900)
orientation before: fvec3(15.757041, 11.546085, 0.494900)
rotation: fvec3(0.000000, 10.181817, 0.000000)
orientation after: fvec3(16.596092, 21.327044, 3.448837)
orientation before: fvec3(16.596092, 21.327044, 3.448837)
rotation: fvec3(6.181818, -0.000000, 0.000000)
orientation after: fvec3(22.777910, 21.327044, 3.448836)
orientation before: fvec3(22.777910, 21.327044, 3.448836)
rotation: fvec3(0.000000, 12.000000, 0.000000)
orientation after: fvec3(25.255577, 32.297348, 8.913291)
orientation before: fvec3(25.255577, 32.297348, 8.913291)
rotation: fvec3(3.636364, -0.000000, 0.000000)
orientation after: fvec3(28.891941, 32.297352, 8.913290)
orientation before: fvec3(28.891941, 32.297352, 8.913290)
rotation: fvec3(0.000000, 12.727273, 0.000000)
orientation after: fvec3(34.057663, 43.175217, 17.306284)
orientation before: fvec3(34.057663, 43.175217, 17.306284)
rotation: fvec3(0.363636, -0.000000, 0.000000)
orientation after: fvec3(34.421299, 43.175220, 17.306288)
orientation before: fvec3(34.421299, 43.175220, 17.306288)
rotation: fvec3(0.000000, 5.636363, 0.000000)
orientation after: fvec3(37.799271, 47.732010, 22.041012)
orientation before: fvec3(37.799271, 47.732010, 22.041012)
rotation: fvec3(-0.909091, -0.000000, 0.000000)
orientation after: fvec3(36.890179, 47.732010, 22.041016)
orientation before: fvec3(36.890179, 47.732010, 22.041016)
rotation: fvec3(0.000000, 12.545454, 0.000000)
orientation after: fvec3(47.936203, 57.054291, 35.913132)
orientation before: fvec3(47.936203, 57.054291, 35.913132)
rotation: fvec3(-10.727273, -0.000000, 0.000000)
orientation after: fvec3(37.208916, 57.054287, 35.913124)
orientation before: fvec3(37.208916, 57.054287, 35.913124)
rotation: fvec3(0.000000, 2.000000, 0.000000)
orientation after: fvec3(39.175983, 58.626469, 38.236393)
orientation before: fvec3(39.175983, 58.626469, 38.236393)
rotation: fvec3(-4.909091, -0.000000, 0.000000)
orientation after: fvec3(34.266888, 58.626469, 38.236393)
orientation before: fvec3(34.266888, 58.626469, 38.236393)
rotation: fvec3(0.000000, 1.272727, 0.000000)
orientation after: fvec3(35.485283, 59.670666, 39.655521)
orientation before: fvec3(35.485283, 59.670666, 39.655521)
rotation: fvec3(-10.181816, -0.000000, 0.000000)
orientation after: fvec3(25.303461, 59.670673, 39.655521)
It almost looks like a rounding error? I'm not sure. I tried normalizing the quaternion during and after the calculation, but it didn't help...
EDIT - Solution
Changed the rotate(..) method to this:
void Camera::rotate(const glm::detail::float32& degrees, const glm::vec3& axis)
{
if ( axis == glm::vec3(0.0f, 1.0f, 0.0f) )
orientationQuaternion_ = glm::normalize(glm::angleAxis(degrees, axis)) * orientationQuaternion_;
else
orientationQuaternion_ = orientationQuaternion_ * glm::normalize(glm::angleAxis(degrees, axis));
}
Still have some work to do here, but it seems to fix the problem from before.
orientationQuaternion_ = glm::normalize(glm::angleAxis(degrees, axis)) * orientationQuaternion_;\$\endgroup\$