The section documents the algorithm used with the virtual trackball.
In order to keep all angles in the range
, an
orientation variable keeps track of which axis you are looking
along, from the set {x+,x-,y+,y-,z+,z-}. There is also a face_orient variable that keeps track of the quadrant of rotations in
the viewing plane, from the set {n,r,u,l} referring to rotations by
and
respectively.
The input to the trackball is effectively a unit stick attached to the
virtual sphere, the endpoints of which are given by xcomp and
ycomp. The third degree of freedom is stored in sinomega,
representing
where
is the rotation around this
``stick''. The output of the virtual trackball routine is the box variable, which contains the projections of the x,y,z axes of the
bounding box, as well as the projection of the origin.
The heart of the virtual trackball consists of constructing the
rotation/projection matrix. Consider a set of rotations
,
and
about the
,
and
axes respectively.
Explicitly, the rotation matrices are given by:



The full rotation matrix is given
, or

Figure: Angle variables defining the virtual trackball
The unit stick is simply
rotated, i.e.
. From
the above expression for
, we find that

The bounding box is then calculated from the rotation/projection
matrix from the bounding box axes (dims.x
, dims.y
and dims.z
) and the origin offs.
The other major part of the algorithm requires keeping track of the bounding box's origin and face orientation. To do this, a transition table is used,
typedef enum {up, right, down, left} transfers;
/* nextface[orientation][direction] */
ag_orient_t nextface[6][4]=
{{{zp,r},{yp,l},{zm,n},{ym,n}}, /* xp orientation */
{{yp,n},{zp,n},{ym,r},{zm,l}}, /* xm orientation */
{{xp,r},{zp,l},{xm,n},{zm,n}}, /* yp orientation */
{{zp,n},{xp,n},{zm,r},{xm,l}}, /* ym orientation */
{{yp,r},{xp,l},{ym,n},{xm,n}}, /* zp orientation */
{{xp,n},{yp,n},{xm,r},{ym,l}}}; /* zm orientation */
inline transfers XFER(const transfers dir)
{return (transfers) ((dir-face_orient)&3);}
and is used for example if we are flipping the cube to the right
new_orient = nextface[orientation][XFER(right)];So if we are facing the x+ direction, and the face is in the r orientation, the new orientation becomes z+, in the r facial orientation.
With the new orientation calculated, we also need to compute where the
unit stick goes. If we are moving to the right, the new stick
will appear on the left hand face of the box. Similarly, moving up,
the stick will appear on the bottom face. To calculate the new
and
, it is simply a matter of applying the
Rotation/Project Matrix (for example moving right):

To calculate the new sinomega, we must apply a consistency
relation. In the case of moving right, we must have
, which implies
, or in other words,
.
The dimensions and origin of the box are handled by a reorient routine, which returns the permuted values from some absolute storage dims_abs and offs_abs. It should also be noticed that the sign of offs.z will depend on whether one is looking in the positive or negative direction along the z axis.