# Tutorial of Arcball without quaternions

Today I’m showing you a little mathematical tutorial about the techniques which are behind the implementation of the ubiquitous and very clever Arcball method. Arcball is a method to manipulate and rotate objects in 3D intuitively.

The motivation behind the Arcball is to provide an intuitive user interface for complex 3D object rotation via a simple, virtual sphere – the screen space analogy to the familiar input device bearing the same name.

If you are here because were searching about quaternions, I’m telling you that Arcball really doesn’t need quaternions to accomplish its simple task!

Arcball algorithm works by defining a hemisphere inscribed in screen area, where $x$ axis is along the screen width and $y$ axis is along the screen height. Also remember that in OpenGL the origin of pixel coordinates $(0,0)$ is in the upper left corner of the window.

The $(x,y)$ mouse coordinates are used to sample from a $z(x,y)$ function:



This means that points inside the circle in figure are mapped on a sphere, while the outer points are mapped in the $z=0$ plane.

Arcball 2d setup

The choice of this function is very smart. It helps rotating 3D objects when the selection is done inside the circle, while in the borders of the screen the rotation is only around $z$ axis, being $z=0$.

The mapping function $z$ allows us to define a start vector $\mathbf{p}_1 = (x,y,z) \in \mathbb{R}^3$ from which we start the rotation.

We proceed with the description of the arcball algorithm. After the first click the start vector is well defined and suddenly after the user is dragging the mouse in the screen area.

Let’s suppose that the user reaches a new position given by $(x',y')$ pixel coordinates. We then remap this pixel coordinates again using the function described before, obtaining a new vector

$\mathbf{p}_2 = (x',y',z(x',y'))$.

User clicks on point p1 on the (x,y) screen area and the point is sampled on the sphere. Then user drags the cursor to reach point (x’,y’) that is mapped to p2. The angle-axis transformation between p1 and p2 is exploited to create the appropriate rotation matrix to apply to our scene.

Now in order to obtain a rotation in terms of a $\mathbb{R}^{3\times 3}$ orthogonal rotation matrix we have to compute the angle between start and end vectors.

It’s simple to show  that the angle $\theta$ formed by the two vectors $\mathbf{p}_1$ and $\mathbf{p}_2$ is

$\theta = \arccos \left( \dfrac{ \mathbf{p}_1 \cdot \mathbf{p}_2 }{ ||\mathbf{p}_2|| \cdot || \mathbf{p}_1 ||} \right)$

and the axis of rotation $\mathbf{u}$ is given by the normalized cross-product of the two vector

$\mathbf{u} = \dfrac{\mathbf{p}_1 \times \mathbf{p}_2 }{||\mathbf{p}_2|| \cdot || \mathbf{p}_1 ||}$

Vector to rotate ModelView matrix around

In OpenGL is then very simple to apply such a rotation, using a glRotate{f,d} function.

There is a standard method to obtain a rotation matrix for this kind of angle-axis transformation, but please forget quaternions, they are difficult and in this very simple case, rather an overkill in my opinion. Some informations can be found at wikipedia page for rotation matrices http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle

Just for clarity the $3 \times 3$ rotation matrix for a 3D axis-angle rotation of $\theta$ radians around a $u$ is given by:



The sphere is a good choice for a virtual trackball because it makes a good enclosure for most any object: and its surface is smooth and continuous, which is important in the generation of smooth rotations in response to smooth mouse movements.
Any smooth, continuous shape, however, could be used, so long as points on its surface can be generated in a consistent way.

I provide a C++ class for Arcball manipulation which only dependency is the matrix library Eigen, in the following snippet:

P.S. If you want to compile the two class with g++ compiler, don’t forget to include your Eigen version

g++ -I/home/user/Desktop/Eigen -c Arcball.cpp Arcball.h -o Arcball.o

I don’t provide an executable or Makefile, so don’t ask me.