So I switched my camera to use quaternions and the first thing I noticed is that things started to 'roll' even though I'm not using any roll values. I looked it up and I found that people suggest that using rotation = horizontal * rotation * vertical
solves the issues instead of rotation = rotation * horizontal * vertical
which I thought was the more intuitive thing from doing matrix multiplication. The explanations I read as to why one works and the other doesn't were pretty vague and unclear.
My question is: why does it work this way? what's wrong with 'rotation * h * v`?
Sample code:
float Horizontal = 0;
float Vertical = 0;
if (Keys['W'] == Key_Held)
{
Camera->Position += Camera->Forward() * CamMovSpeed * DeltaTime;
}
if (Keys['S'] == Key_Held)
{
Camera->Position -= Camera->Forward() * CamMovSpeed * DeltaTime;
}
if (Keys['A'] == Key_Held)
{
Camera->Position -= Camera->Right() * CamMovSpeed * DeltaTime;
}
if (Keys['D'] == Key_Held)
{
Camera->Position += Camera->Right() * CamMovSpeed * DeltaTime;
}
if (Keys['E'] == Key_Held)
{
Camera->Position += vec_Up * CamMovSpeed * DeltaTime;
}
if (Keys['F'] == Key_Held)
{
Camera->Position -= vec_Up * CamMovSpeed * DeltaTime;
}
// mouse
int dx = Mouse->x - Mouse->LastX; Mouse->LastX = Mouse->x;
int dy = Mouse->LastY - Mouse->y; Mouse->LastY = Mouse->y;
if (Mouse->MMB == Key_Held) // pan
{
Camera->Position -= (Camera->Up()*dy + Camera->Right()*dx) * SpeedMul/2 * DeltaTime;
}
if (Mouse->RMB == Key_Held) // orbit
{
Horizontal += dx * SpeedMul*10 * DeltaTime;
Vertical += dy * SpeedMul*10 * DeltaTime;
}
if (Mouse->Wheel) // zoom
{
Camera->Position += Camera->Forward() * Mouse->Wheel * SpeedMul*10 * DeltaTime;
}
if (Horizontal != 0 || Vertical != 0)
{
quat QVertical(vec_Right, -Vertical);
quat QHorizontal(vec_Up, Horizontal);
Camera->Rotation = QHorizontal * Camera->Rotation * QVertical; // this works
//Camera->Rotation = Camera->Rotation * QHorizontal * QVertical; // this doesn't
Camera->Rotation.Normalize();
}