4
$\begingroup$

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?

$\endgroup$
  • $\begingroup$ In case it provides any help, according to 3dgep.com/understanding-the-view-matrix/#Look_At_Camera some signs are changed, which would not make sense according to me, as it does not make sense with the rotation matrix multiplication results. You can check that in the FPS camera section $\endgroup$ – rustyBucketBay Sep 26 at 17:51
  • $\begingroup$ Oh In the case if the example provided it says that "The basic theory of this camera model is that we want to build a camera matrix that first rotates pitch angle about the X axis, then rotates yaw angle about the Y axis, then translates to some position in the world" that means that the order of the rotation is inverted. So if I do RpT * RyT, the signs are correct. Sorry if that was confusing $\endgroup$ – rustyBucketBay Sep 26 at 18:00
1
$\begingroup$

It's happening because they just happened to define the rotation matrix with counterclockwise rotation direction, which is the common convention for polar$\rightarrow$cartesian coordinate system transformation. If you google for the transformation, you'll see that the angle is universally shown to rotate to the counterclockwise direction like below

enter image description here

| improve this answer | |
$\endgroup$
  • $\begingroup$ Only the yaw is inverted, the pitch works as expected. $\endgroup$ – user5488 Nov 16 '16 at 20:41
  • $\begingroup$ Are you saying that the rotation doesn't happen to the counterclockwise direction with increasing angles in your coordinate system? $\endgroup$ – JarkkoL Nov 16 '16 at 20:55
  • $\begingroup$ It is counterclockwise on the Y axis (the yaw), i.e. increasing the angle (or looking right) causes the fixed object the camera is looking at to go right, but clockwise on the X axis (the pitch), increasing the angle (looking up) causes the object to go down as expected. $\endgroup$ – user5488 Nov 16 '16 at 21:09
  • $\begingroup$ What's the coordinate system you are using (x=right, etc)? $\endgroup$ – JarkkoL Nov 17 '16 at 22:18
  • $\begingroup$ Right handed system with +x is right, +y is up $\endgroup$ – user5488 Nov 17 '16 at 22:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.