Bonus: Alternative projectOntoSurface
Note how with the current implementation, if you drag outside the sphere it maps to the closest point on the sphere rather than continuing the rotation. To make the rotation continue instead, replace the else clause in projectOntoSurface with this:
P.z = radius2 / (2.0 * sqrt(length2));
float length = sqrt(length2 + P.z * P.z);
P = GLKVector3DivideScalar(P, length);
Bonus: More Fun with Quaternions
You might wonder what else you can do with quaternions. One cool thing they can do is provide an easy way to interpolate between two rotations over time.
To see what I mean, let's try it out and add some code to make our cube animate back to its original orientation if you double tap. Make the following changes to HelloGLKitViewController.m:
// Add new private instance variables
BOOL _slerping;
float _slerpCur;
float _slerpMax;
GLKQuaternion _slerpStart;
GLKQuaternion _slerpEnd;
// Add to bottom of setupGL
UITapGestureRecognizer * dtRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTap:)];
dtRec.numberOfTapsRequired = 2;
[self.view addGestureRecognizer:dtRec];
// Add new method
- (void)doubleTap:(UITapGestureRecognizer *)tap {
_slerping = YES;
_slerpCur = 0;
_slerpMax = 1.0;
_slerpStart = _quat;
_slerpEnd = GLKQuaternionMake(0, 0, 0, 1);
}
// Add inside update method, right before declaration of modelViewMatrix
if (_slerping) {
_slerpCur += self.timeSinceLastUpdate;
float slerpAmt = _slerpCur / _slerpMax;
if (slerpAmt > 1.0) {
slerpAmt = 1.0;
_slerping = NO;
}
_quat = GLKQuaternionSlerp(_slerpStart, _slerpEnd, slerpAmt);
}
When the user double taps, we set the start rotation to the current orientation (_quat), and the end rotation to the "identity" quaternion (no rotation at all).
Then inside update, if we are "sleeping" we figure out how far along the animation we are so far. Then we use the built-in GLKQuaternionSlerp method to come up with the appropriate rotation in-between slerpStart and slerpEnd, based on the current time.
Compile and run, rotate the object, and double tap to make it animate back to its original position. This technique is commonly used for keyframe animations on 3D objects and the like.
Where To Go From Here?
Here is an example project with all of the code from the above tutorial.
Hopefully this tutorial was helpful to others who wanted to learn a little more about rotating 3D objects based on touches and brush up on some 3D math concepts.
If anyone has any questions, corrections, or better or easier ways to explain things, please join the forum discussion below!
This is a blog post by site administrator Ray Wenderlich, an independent software developer and gamer.