5
\$\begingroup\$

I wish to orbit a camera around a sphere, yet the problem is that when the camera rotates so that it is at the north pole (and pointing down) or the south pole (and pointing up) of the sphere the camera doesn't handle itself very well. It spins rapidly until arriving 180 degrees in the opposite direction. I believe this is known as gimbal lock.

I understand you can avoid this problem using quaternions. But I also read in another forum that it's possible to avoid this easily using euler angles as well. Which I would prefer to do. It was said that all you need to do is "calculate a proper up-vector every frame, and that avoids the problem entirely."

Well, I tried aligning the up-vector with the vertical axis of the camera whenever the camera changed orientation, but this didn't seem to work. Meaning that the up-vector followed exactly the orientation of the camera's y-axis (or it's up vector), instead of using a constant up-vector aligned to the up-vector of the world (0, 1, 0).

How exactly do I go about calculating a proper up-vector as my camera orientation changes to avoid the gimbal lock problem mentioned above?

\$\endgroup\$
3
  • \$\begingroup\$ Can you edit the question to give more detail on just what the problem is that you're trying to solve? "Gimbal lock" isn't specific enough to tell us what the trouble is. \$\endgroup\$ Commented Jun 5, 2012 at 20:38
  • \$\begingroup\$ sure. the question has now been edited to provide more detail. Let me know if the problem is still not described well enough. I do not post very often, so I'm inexperienced at this. \$\endgroup\$ Commented Jun 5, 2012 at 20:56
  • 1
    \$\begingroup\$ I'm going to leave a bit of Carmack wisdom here: "You will eventually regret any use of Euler angles." \$\endgroup\$
    – knight666
    Commented Jun 6, 2012 at 7:11

2 Answers 2

10
\$\begingroup\$

That's not gimbal lock: the camera simply aligns itself with the up vector and then you get a camera transformation matrix that's rank deficit. In not so mathematical terms, try to mind this: you must rigidly rotate the camera's lookAt and upVector together (using the same transform/rotation). I repeat, this is totally NOT gimbal lock, but it's quite similar in one aspect: you lose one degree of freedom since you end up with ambiguities when you align the up vector with the look at vector.

Short solution: keep track of both lookAt and upVector and transform them together. That should work just fine (mathematically, but not necessarily optimized from a computational point of view).

\$\endgroup\$
1
  • 5
    \$\begingroup\$ And don't forget to re-normalize if you apply incremental rotations without resetting; I did that once and cumulative floating point errors will get you fast =) \$\endgroup\$ Commented Jun 5, 2012 at 23:31
3
\$\begingroup\$

That absolutely is gimbal lock actually, and it's impossible to avoid using Euler angles unless you explicitly have a way to find and use a new up vector to compensate for when the camera is approximately parallel to (0,1,0) i.e. abs(dot(camlook, [0,1,0])) is approximately equal to 1. Just check for that case, and then pick a new "up" vector and calculate your rotation with respect to that vector instead.

Quaternions are a way to avoid this, although you could potentially just use rotation matrices as well and concatenate them. What you'd have to do to use quaternions is to take the camera's angular velocity (technically it isn't really angular velocity but whatever) and represent it as a quaternion. Now, a quaternion is nothing more than a representation of an axis and an angle of rotation, so what you need to do is figure out how many radians (or degrees) the camera rotates every second and then what axis it rotates about. Use these two values to compute a quaternion.

Now, take the camera's initial orientation and represent that as a quaternion also (or use the identity quaternion, which is [0,0,0,1] for [x,y,z,w]). To make rotation happen, all you have to do is multiply the quaternions, however the way you have it represented you would be rotating in some fixed step once per second, which is not smooth at all. There are two ways that you can smooth this out.

The first is that you can instead represent the camera's rotation speed at a smaller unit of time than 1 second, say 1 frame maybe, and then just multiply quaternions. This will work fine if you have a fixed frame rate that never varies and even if it varies a bit, it will probably still look decent.

The other thing you can do is what's called a spherical linear interpolation (SLERP), which is a way of interpolating one quaternion onto another. The way to do this is to take the camera's quaternion and then multiply it by the rotation quaternion as before, and store that in a temporary variable. This will be the position that the camera will be in after 1 second. Now, SLERP interpolates between 0 and 1, and in this case you have the camera's current position, which is at the current time, so no change in time i.e. 0, and then the camera's position after 1 second, so conveniently enough you have those two values, so if you use SLERP and give it a value that is the change in time from the last time you updated, that will allow you to compute a new quaternion, which will be the rotation amount that you want for this frame, and then you just multiply that new quaternion by your camera's current quaternion and you're done.

You ultimately need a rotation matrix though for the camera, but turning a quaternion into a rotation matrix is not particularly difficult (it's just math). Don't forget, if you're orbiting a point that isn't at the origin, you'll need to first do a change of basis on the camera so that it's position/rotation/scale/etc. is in the basis of the object that it's rotating about. If the camera's rotation is independent of the sphere i.e. the sphere is not rotating or if it is rotating, the camera doesn't care about that, then just subtract the sphere's world position from the camera's position, then apply your rotation, then add the sphere's world position back to the camera's position. I don't know what math library you're using, but directx math has the necessary quaternion functions that you'll need including SLERP. If you just want to implement these on your own, you'll have to look up the necessary math but it isn't particularly difficult to do (although it's very hard to actually understand what it's doing and why it works, at least in my opinion).

\$\endgroup\$
4
  • 4
    \$\begingroup\$ -1: "That absolutely is gimbal lock actually" No it isn't. \$\endgroup\$ Commented Jun 5, 2012 at 23:00
  • 1
    \$\begingroup\$ So the axis of the camera's rotation and the up-vector are collapsing to the same axis, thus losing a degree of freedom in rotation and causing it to spin uncontrollably since there are an infinite number of orthonormal bases that can be constructed when two vectors are parallel. How is that not gimbal lock? \$\endgroup\$ Commented Jun 7, 2012 at 19:25
  • 2
    \$\begingroup\$ Gimbal Lock does not refer to anything that causes a loss of a degree of freedom. It refers to the specific circumstances causes when 3 axial rotations cause a loss of a degree of freedom. The name comes from a physical object called a gimbal, structures that rotate on an axis. Much like Euler angles. If you don't have gimbals, you can't have gimbal lock. You can convert this problem into gimbal lock, by converting the directions into gimbals. But that's still a conversion. \$\endgroup\$ Commented Jun 7, 2012 at 20:02
  • \$\begingroup\$ That is actually the opposite side of the same coin. Regardless of what you call it, when you have a conversion from a quaternion to Euler angles and the resulting pitch angle is +/-90 deg you have a singularity. Pitch has lost coupling with yaw and roll directions -- the loss of unique relationship between the independent axis. This condition is what is called "gimbal lock", a "singularity" condition. Arguing over what to call it makes little sense. \$\endgroup\$ Commented Jun 30, 2023 at 23:48

You must log in to answer this question.

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