A while back Apple finally added some basic 3d classes with GLKit. They included vectors, matrices, and even quaternions. Awesome! Time to do some arcball rotation! Well, I googled myself silly and couldn’t dig up a single sample of using these classes to do a simple object rotation. There are tons of articles about quaternions, gimbal lock, SLERP, and so forth, but I couldn’t locate a basic iOS arcball example. The clearest code I could find is here, but it’s straight C and uses its own Vector and Matrix classes. Arguably straight C can be faster, but wouldn’t it be great to get this all nice and Objective? Well, below is a simple snippet based on the above that uses GLKit. You can plug this right into the Xcode OpenGL Game template, et voila.
#define RADIANS_PER_PIXEL (M_PI / 320.f) /** * do this in viewDidLoad * * these are class variables: CGPoint iniLocation; GLKQuaternion quarternion; */ - (void) initArcBall { quarternion = GLKQuaternionMake(0.f, 0.f, 0.f, 1.f); iniLocation = CGPointMake(0.f, 0.f); } /** * do this in update // skip auto rotation //baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); // rotate with quaternion instead [self rotateMatrixWithArcBall:&baseModelViewMatrix]; */ - (void) rotateMatrixWithArcBall:(GLKMatrix4 *)matrix { GLKVector3 axis = GLKQuaternionAxis(quarternion); float angle = GLKQuaternionAngle(quarternion); if( angle != 0.f ) *matrix = GLKMatrix4Rotate(*matrix, angle, axis.x, axis.y, axis.z); } // ------------------------------------------------------------------------------------------ - (void) rotateQuaternionWithVector:(CGPoint)delta { GLKVector3 up = GLKVector3Make(0.f, 1.f, 0.f); GLKVector3 right = GLKVector3Make(-1.f, 0.f, 0.f); up = GLKQuaternionRotateVector3( GLKQuaternionInvert(quarternion), up ); quarternion = GLKQuaternionMultiply(quarternion, GLKQuaternionMakeWithAngleAndVector3Axis(delta.x * RADIANS_PER_PIXEL, up)); right = GLKQuaternionRotateVector3( GLKQuaternionInvert(quarternion), right ); quarternion = GLKQuaternionMultiply(quarternion, GLKQuaternionMakeWithAngleAndVector3Axis(delta.y * RADIANS_PER_PIXEL, right)); } - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInView:self.view]; iniLocation = location; } - (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInView:self.view]; // get touch delta CGPoint delta = CGPointMake(location.x - iniLocation.x, -(location.y - iniLocation.y)); iniLocation = location; // rotate [self rotateQuaternionWithVector:delta]; }
Strange?

This is great! Simple and effective.
Cheers man
[...] Arcball rotation with GLKit [...]
Thanks for this, been looking for something like this for a while. Can’t quite get it to work just plugging it straight in – probably missing something really simple.
I can see what’s supposed to happen so it’s helped me enormously anyway – thanks again.
Hey, thank you for your tutorial. Very elegant and helpful.
A small remark: The source code above rotates the cube forever once it is touched. To avoid this behaviour change the following line in rotateMatrixWithArcBall:
*matrix = GLKMatrix4Rotate(*matrix, angle, axis.x, axis.y, axis.z);
to
*matrix = GLKMatrix4MakeRotation(angle, axis.x, axis.y, axis.z);
This creates a new matrix that represents the orientation that is stored in the quarternion instead of constantly multiplying the current rotation matrix with a rotation matrix.
Another remark: This is not an actual arcball implementation. This code only maps dX and dY to rotation on X and Y axis. The arcball uses an virtual ball as an interaction metapher. Touch points are mapped from the 2D screen to the surface of a sphere. A rotation axis and angle is calculated and used to create the quaternion / matrix. The theory is explained here: http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Arcball