1
\$\begingroup\$

I have a camera that works with Pitch and Yaw (no roll) and compute the look at matrix as following :

glm::vec3 direction;
direction.x = cos(glm::radians(pitch)) * cos(glm::radians(yaw));
direction.y = sin(glm::radians(pitch));
direction.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw));
direction   = glm::normalize(direction);
this->view =
  glm::lookAt(position, position + direction, glm::vec3(0, 1, 0));

Now I want to initialize these Pitch and Yaw from another View Matrix and used this method but without success:

  /* previousCamera->view as a glm::mat4 */
  position = glm::vec3(previousCamera->view[3]);
  const glm::vec3 direction = glm::vec3(previousCamera->view[2]);
  yaw   = glm::degrees(glm::atan(direction.x, direction.z));
  pitch = glm::degrees(glm::asin(direction.y));

Do you spot any mistake in my code?


Edit:

In addition to the answer from @DMGregory, my position and direction were not correctly extracted from the ViewMatrix:

  const glm::mat4 inverted = glm::inverse(previousCamera->view);
  position = glm::vec3(inverted[3]);
  const glm::vec3 direction = - glm::vec3(inverted[2]);
  yaw   = glm::degrees(glm::atan(direction.z, direction.x));
  pitch = glm::degrees(glm::asin(direction.y));
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

First, let's look at y because it's simplest.

  • to encode pitch into your direction vector's y, you convert the pitch value to radians, then take its sine.

  • to decode pitch from your direction vector's y, you take its arcsine and then convert it to degrees.

So you're correctly reversing each operation, and the value should round-trip correctly up to floating point accuracy.

yaw / x and z get a bit more complicated, so let's try running a few sample values through (with zero pitch, for simplicity):

  • at yaw = 0, x = cos(0) = 1 and z = sin(0) = 0

    • at (x, z) = (1, 0), yaw = degrees(atan(1, 0)) = 90 degrees
  • at yaw = 90 degrees, x = cos(radians(90)) = 0 and z = sin(radians(90)) = 1

    • at (x, z) = (0, 1), yaw = degrees(atan(0, 1)) = 0 degrees

So it looks like you've simply flipped your x and z arguments to atan.

If you think of the two-argument arctangent as finding an angle from positive x-axis on the unit circle in the xy plane, the arguments go in the order (y, x) rather than (x, y)

\$\endgroup\$
1
  • \$\begingroup\$ Nice answer. My Position and Direction were also not correctly extracted. I edited my post. \$\endgroup\$
    – FloFu
    Jul 8, 2018 at 10:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .