0
\$\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
\$\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\$
  • \$\begingroup\$ Nice answer. My Position and Direction were also not correctly extracted. I edited my post. \$\endgroup\$ – FloFu Jul 8 '18 at 10:28

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.