Direction, orientation, rotation
by R. Niehoff
Direction
The direction is simply a normal 3D vector. The moving direction is a typical example, represented by the velocity vector. Other examples you can find in the real world: light ray of a torch light, viewing direction when looking around, flight path of an arrow. It's apparent that you can define all possible directions in the 3D world with a simple vector. There are other ways of defining a direction. So you can use 2 angles (head and pitch) but for computing the motion and view direction in a 3D program the vector is more comfortable.
You don't need the magnitude of the vector, only the component that represents the direction. That means that you often work with normalized vectors. You might think that the magnitude of a velocity vector can't be ignored. That's right, but remember that the velocity contains more than only the direction, it contains the absolute speed, too. For changing the direction (= rotating the vector) you have to create a rotation matrix and multiply the vector with this matrix.
Orientation
In the first view you might think: isn't it the same as direction? Indeed, to beam the light into a desired direction you have to orientate the torch light in just this direction. Not a good example, the camera analogy is more significant. You put the camera on a tripod and focus it to the person you want to shoot. Unconsciously you pay heed to orientate the camera horizontally. And now you keep the person in the middle of the viewport and rotate the camera around its own axis. The direction will still be the same but the orientation changes.
You see, the full orientation consists of a direction component and an additional rotation angle. In respect to Tux this angle is used for simulating a realistic turning. Compare it with a biker in a curve and imagine what will happen if he keeps his upright position. Another case: Tux moves on sloped terrain and of course has to be orientated on the surface, independent of his moving direction. Compare it with a car, all wheels touch the road (sure, there might be special situations, for example a roadside ditch). That's why the surface normal is so important, it defines the orientation among other things.
Orientation in a program
And now the problem: how to define a full orientation and how to handle it? A vector for the direction and an additional angle? In some rare cases it might be practical. The gluLookUp camera function of OpenGL uses an additional vector (up vector) for calculating the full orientation. But the calculation fails in extreme positions. Generally, the solutions based on angles or a mix of angles and vectors have two disadvantages:
- The values can't be properly interpolated. The interpolation is used for smooth adaption of motion and for keyframes.
- A "gimbal lock" might occur. The gimbal lock describes an undefined state where two or more parameters coincide. That results in a loss of information and an undefined behaviour.
The best solution is to use quaternions. A quaternion is defined as a sum of one real number and three complex numbers with different imaginary components:
A quaternion is an abstract mathematical strukture with a bundle of defined rules, and these rules are very helpful to handle the orientation without the mentioned disadvantages. For the proposed usage in 3D programs the quaternion can defined as a 4-dimensional vector
where v contains the direction vector and w represents the additional angle. But have in mind that v is not an ordinary vector, the direction vector as well as the rotation angle must be converted to the quaternion about a matrix. Same with the reverse procedure. The calculation rules (conjugation, inversion ...) of the quaternion allow to do the desired operations in a proper way: you can arbritary rotate the body of Tux and interpolate the orientation smoothly. Best of all: the complete information is stored in a small vector with 4 real numbers.
I suppose that not many people are familiar with quaternions. To study how it works you can have a look in view.cpp, tux.cpp and mathlib.cpp.