Skip to main content
6 of 6
deleted 55 characters in body
user5488
  • 156
  • 1
  • 4

Inverted yaw angle in the view matrix

I'm trying to construct a FPS view matrix for my OpenGL renderer using yaw and pitch angles instead of the typical LookAt view matrix.

The view matrix is the inverse of the camera world transform $\mathbf{M}_{\textrm{view}} = (\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1}$, hence:

$$\small\begin{align} (\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1} &= \mathbf{R}_y^{T}\mathbf{R}_p^{T}\mathbf{T}^{-1} \\ &= \begin{bmatrix} \cos{y} & 0 & \sin{y} & 0 \\ 0 & 1 & 0 & 0 \\ -\sin{y} & 0 & \cos{y} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}^T \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos{p} & -\sin{p} & 0 \\ 0 & \sin{p} & \cos{p} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}^T \begin{bmatrix} 1 & 0 & 0 & e_0 \\ 0 & 1 & 0 & e_1 \\ 0 & 0 & 1 & e_2 \\ 0 & 0 & 0 & 1 \end{bmatrix}^{-1} \\ &= \begin{bmatrix} \cos{y} & 0 & -\sin{y} & 0\\ 0 & 1 & 0 & 0 \\ \sin{y} & 0 & \cos{y} & 0\\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & \cos{p} & \sin{p} & 0\\ 0 & -\sin{p} & \cos{p} & 0\\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & -e_0\\ 0 & 1 & 0 & -e_1\\ 0 & 0 & 1 & -e_2\\ 0 & 0 & 0 & 1\\ \end{bmatrix} \\ &= \begin{bmatrix} \cos{y} & \sin{p}\sin{y} & -\cos{p}\sin{y} & -e_0\cos{y} - e_1\sin{p}\sin{y} + e_2\cos{p}\sin{y}\\ 0 & \cos{p} & \sin{p} & -e_0 \cdot 0 - e_1 \cos{p} - e_2 \sin{p}\\ \sin{y} & -\cos{y}\sin{p} & \cos{p}\cos{y} & -e_0\sin{y} + e_1\cos{y}\sin{p} - e_2\cos{p}\cos{y}\\ 0 & 0 & 0 & 1 \end{bmatrix} \end{align}$$

Every step is double checked using WolframAlpha.

The implementation:

inline Matrix4
FPSViewRH(const Vector3& eyePosition, float yaw, float pitch) noexcept
{
  yaw = Utils::Radians(yaw);
  pitch = Utils::Radians(pitch);

  const auto sinYaw = std::sin(yaw);
  const auto cosYaw = std::cos(yaw);

  const auto sinPitch = std::sin(pitch);
  const auto cosPitch = std::cos(pitch);

  const Vector3 i{cosYaw, sinPitch * sinYaw, -cosPitch * sinYaw};
  const Vector3 j{0, cosPitch, sinPitch};
  const Vector3 k{sinYaw, -cosYaw * sinPitch, cosPitch * cosYaw};

  return {
    {i[0], i[1], i[2], -i.Dot(eyePosition)},
    {j[0], j[1], j[2], -j.Dot(eyePosition)},
    {k[0], k[1], k[2], -k.Dot(eyePosition)},
    {0,    0,    0,    1},
  };
}

It works fine except that the yaw is inverted, i.e. increasing the angle causes the object to go right while it should go left.

I can negate the yaw angle or change every $\sin{y}$ to $-\sin{y}$, but I don't really understand why this is happening?

user5488
  • 156
  • 1
  • 4