0
\$\begingroup\$

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();
}
\$\endgroup\$
4
  • \$\begingroup\$ Don't use quaternions for cameras, people think in euler angles not in quaternions \$\endgroup\$
    – Bálint
    Mar 4, 2017 at 23:56
  • \$\begingroup\$ I will be changing the camera back to eulers eventually. But will be using quaternions for objects rotation. I would still like to understand why this behavior happens. I don't like to just use a different system just because I came across something I don't understand. \$\endgroup\$
    – vexe
    Mar 5, 2017 at 0:03
  • 1
    \$\begingroup\$ I've written up a description of why this happens here: (with lots of animated gifs!) I'm rotating an object on two axes, so why does it keep twisting around the third axis? - your alternate multiplication order effectively applies the "pitch local, yaw global" advice at the bottom. \$\endgroup\$
    – DMGregory
    Mar 5, 2017 at 2:48
  • \$\begingroup\$ Awesome thanks! Much better than "just don't do it" \$\endgroup\$
    – vexe
    Mar 5, 2017 at 3:05

0

Browse other questions tagged .