Advertisement

Why does glm::lookat works this way?

Started by August 30, 2020 08:56 PM
3 comments, last by JoeJ 4 years, 2 months ago

If you take a look at the code:

template<typename T, qualifier Q>
	GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAtLH(vec<3, T, Q> const&amp; eye, vec<3, T, Q> const&amp; center, vec<3, T, Q> const&amp; up)
	{
		vec<3, T, Q> const f(normalize(center - eye));
		vec<3, T, Q> const s(normalize(cross(up, f)));
		vec<3, T, Q> const u(cross(f, s));

		mat<4, 4, T, Q> Result(1);
		Result[0][0] = s.x;
		Result[1][0] = s.y;
		Result[2][0] = s.z;
		Result[0][1] = u.x;
		Result[1][1] = u.y;
		Result[2][1] = u.z;
		Result[0][2] = f.x;
		Result[1][2] = f.y;
		Result[2][2] = f.z;
		Result[3][0] = -dot(s, eye);
		Result[3][1] = -dot(u, eye);
		Result[3][2] = -dot(f, eye);
		return Result;
	}

glm calculates the direction vector f by subtracting the eye (for example camera position) from something that is called the center.

So if for example, you have a camera with camPos and camFront (camera position and direction) then you call glm::lookat like this:

glm::lookat(camPos, camPos - camFront, worldUp)

and then glm calculates the f direction like this:

f = center-eye =  camPos - camFront - camPos = -camFront

So it basically ends up looking at the camFront (negated). But why does it have to do this calculation? Why can't just take the camFront directly instead of that center? It does an unnecessary calculation…


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

babaliaris said:
Why can't just take the camFront directly instead of that center?

Sometimes you want align stuff to the front vector, sometimes to the eye vector. For a perspective view the eye vector can be different. For example if you use a mouse cursor to point at some object on screen, but the object is not at the center of the screen. Not to mention we use look at matrices for other purposes too, not just for camera stuff.

Ofc, if you already have a unit vector, then glm wastes the normalization on recalculating it.

Advertisement

What happens when the forward direction f becomes parallel with the up vector (Looking at the scene from top-down)?

glm::lookat will not be able to calculate this cross product:

vec<3, T, Q> const s(normalize(cross(up, f)));

I've noticed that if I try to do a full 360 degrees rotation with my camera around the x-axis then something weird happens when the pitch value becomes greater than 89.99999 degrees. It seems like the whole scene flips upside down.


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

babaliaris said:
What happens when the forward direction f becomes parallel with the up vector (Looking at the scene from top-down)?

The functions fails on division by zero.

Discussed this recently here: https://www.gamedev.net/forums/topic/707867-lookat-how-to-get-the-correct-temporary-vector-up/

The proposed solution is to use a different up vector orthogonal to the original one. But there is no clear answer what this alternative up vector should be.
We get a matrix that still looks at the target but no longer respects the up vector. And even this would break if target == eye.

This topic is closed to new replies.

Advertisement