Gimbal lock while orbiting camera around interest point

Hi,

I’m trying to make a camera orbit around the interest point.
I’m applying a rotation matrix to the inverse of the forward vector of camera, then multiplying it for the distance between camera and interest point.
Finally I add the interest point to the forward vector and I got the new position for the camera.
Then I setup the new forward, right and up vector for the camera.

I’m using quaternions for the rotation and the result is pretty working, but I have gimbal lock when the camera foward vector gets close to the x axes in the global coord system.

this is the code:

Quaternion q;
Matrix m;
Vector vf( camForward );

q.FromEuler( y, x, 0 );
q.ToRotationMatrix( m );

vf.Mul( -1.0f );
vf.Mul( vf, m );
vf.Normalize();
vf.Mul( camDistance );

camPosition.Add( camInterest, vf );

camForward.Sub( camInterest, camPosition );
camForward.Normalize( );

camRight.Cross( camForward, camUp );
camRight.Normalize( );

camUp.Cross(  camRight, camForward );
camUp.Normalize( );
  

Do you see some logical error in my code?
I really don’t undestand how I get so easily gimbal lock, even using quaternions!

Please, help me, I don’t know what to try!

Thank you,
Remedios

Without being able to completely infer what the calls
your code makes actually do, I think I see why the
problem is there. You have to keep the “state of the
camera” as a quaternion at all times (store it and
keep track of it), and revert to direction cosines
for your GL calls.

In the following link:
http://www.gamedev.net/reference/articles/article1095.asp
it is stated that you can get a Gimbal lock with
quaternions if you are using them naivly. Never
go from Euler angles to quaternion, only from
direction cosines and back. Somebody told me once:
“Forget about the Euler angles.”

I hope this is helpful. Sorry for the “poor in detail”
response.

Ditch the Eulers.

The other rotation representations (basis matrix, quaternion, axisangle) each have particular advantages. Euler angles, on the other hand, are utterly worthless; as far as I know there’s nothing you can do with them that can’t be done much better another way. If I were you I’d grep your codebase for “euler” and delete everything I found. I did, and have never regretted it.

In your particular case, you have incremental rotations around the X and Y axes (plus a null rotation around the Z axis) and you want to composite them without gimbal lock. So take those individual rotation values and use them as the components of an axis vector. Use the length of that vector as an angle. Bingo: you have a perfectly good AxisAngle representation, with no gimbal lock and no need for eulers. (Or quaternions, for that matter.)

Thank you for your replies,
I checked some articles about quaternions, and I think I will represent my camera as a direction quaternion, position point, interest point, and up vector.

I can handle rotation in local camera space using the quaternion, my bigger problem is when I want to orbit around the interest point.
In fact, this is not only a rotation for the forward vector, but moreover a change of the position of camera.

What I want to have is the same kind of orbiting behavior you have in 3D modeling programs, like blender, Softimage, 3DStudio Max.
I expecially like the softimage behavior, that makes you stop when your forward vector matches the y axis of global coordinate system (and camera looks straight down).

I checked a couple of opensource libraries, but I can’t find anything like that…

How would you suggest to proceed?

Thank you again,

Remedios

I insist on using a quaternion for orientation. Since
you can integrate the quaternion, all you need is to
have a rate of change of the angle and integrate it.

You need to look at how the pitch/roll/yaw rates
constribute to the integration of the quaternion.
Then, from the change in the position vector as the
camera orbits, you can get an angle of rotation (in
radians) and then set a “yaw rate” that corresponds
to that kind of an update in the angle. Simply, set
the timestep to unity (1.0) and the yaw rate to the
angle that the camera needs to rotate in order to
keep looking at the object after the change in the
camera’s position. The result should be, in theory,
what you would expect from an orbiting camera. You
will need to calibrate every now and then to correct
for trancation errors, etc.

Another thing to do is look at the source code for
blender itself.

Finally, if you will not be doing arbitrary rotations,
and you will constrain yourself to looking at an
object from different views (as is done with Blender
when you hit the numeric pad keys to orbit around
the object), simply use direction cosines and apply
simple matrix transformations that you build at
will to do the job. It all depends on what you need.

Here’s a way to do this with good 'ol Euler angles (for the 3 people in the universe that might be interested):

glLoadIdentity();
glTranslatef( 0, 0, -orbitRadius );
glRotatef( -pitch, 1, 0, 0 );
glRotatef( -yaw, 0, 1, 0 );
glTranslatef( -pivot.x, -pivot.y, -pivot.z );

This will work, given Y as the up-axis (as an example). This is simple, intuitive, and does not suffer from Gimbal-lock. It is also easy to restrict the pitch angle to, say, +/-90 degrees, to prevent the camera from turning over.

I’ll bet you this is how Blender does it. I’d be willing to wager 2 bits :slight_smile:

Hi everybody!
I finally found a way to make it works. :slight_smile:

Now I define the camera with position, interest point, a quaternion for the orientation and a roll.

Finally I combine the quaternion with roll and the quaternion with orientation and I get a rotation matrix which I apply to the camera starting axes.

The method is working perfectly for getting up and right vector, but it doesn’t for the forward vector.

Let’s say I have an orientation quaternion, and the roll is zero, if I multiply the starting axes for the quaternion I obtain a perfect up vector and right vector, but the forward vector is different from what I obtain subtracting the interest point from the position point and normalizing it.

For example, when I init the camera I setup the quaternion as ( forward.x, forward.y, forward.z, 0 ), and if I multiply the vector ( 0, 0, 1 ) for the quaternion I don’t get the forward vector back, but something different.

I know I’m missing something, do you have any idea about this behavior?

You are being really helpful, thanks! :slight_smile:

Remedios

I think you are confusing the use of vectors and
quaternions. You typically use the quaternion to get
direction cosines, meaning you need four pieces of
information to get the orientation of an object. The
most useful thing in OpenGL is direction cosines, an
orthonormal basis that is aligned with your object.

Search the web for quaternion algebra and integration.
Also, look for how to go from direction cosines to
quaternion and vice versa. You will need to initiate
the quaternion from the initial direction cosines.
Then, you will keep integrating the quaternion (and
normalizing it) using pitch, yaw and roll rates.
From that you get a new quaternion and from that
you get a new set of direction cosines. You use
this new set in OpenGL.

Unless I have misunderstood you, you only need to
read and understand the use of the quaternions.
For this you can easily search the web and find
something.