I'm using CMDeviceMotion and the attitude's quaternion to obtain the pitch and yaw values, which are then applied to a CC3Camera in a Cocos3D scene to rotate the camera around.
#define RadiansToDegrees(x) ((180 / M_PI) * x)
- (void)initializeScene
{
//...
CC3Camera *cam = [CC3Camera nodeWithName:@"Camera"];
cam.location = cc3v(0, 10, 0.0001);
cam.targetLocation = cc3v(0, 0, 0);
_cameraBoom = [CC3Node nodeWithName:@"CameraBoom"];
_cameraBoom.location = cc3v(0, 0, 0);
[_cameraBoom addChild:cam];
[self addChild:_cameraBoom];
[self setActiveCamera:cam];
_cameraBoom.rotation = cc3v(0, 90, 0);
//...
_motionManager = [[CMMotionManager alloc] init];
_referenceAttitude = nil;
_initialCameraRotation = _cameraBoom.rotation;
[self enableMotion];
}
- (void)enableMotion
{
CMDeviceMotion *deviceMotion = _motionManager.deviceMotion;
_referenceAttitude = deviceMotion.attitude;
_initialCameraRotation = _cameraBoom.rotation;
[_motionManager startDeviceMotionUpdates];
if (!_gyroTimer) {
_gyroTimer = [NSTimer scheduledTimerWithTimeInterval:1 / 30.0
target:self
selector:@selector(doGyroUpdate)
userInfo:nil
repeats:YES];
}
}
- (void)doGyroUpdate
{
CMDeviceMotion *deviceMotion = _motionManager.deviceMotion;
CMAttitude *attitude = deviceMotion.attitude;
if (_referenceAttitude != nil) {
[attitude multiplyByInverseOfAttitude:_referenceAttitude];
}
CMQuaternion quat = attitude.quaternion;
double pitch = RadiansToDegrees(atan2(2 * (quat.x * quat.w + quat.y * quat.z), 1 - 2 * (quat.x * quat.x + quat.z * quat.z)));
double yaw = RadiansToDegrees(asin(2 * (quat.x * quat.y + quat.w * quat.z)));
_cameraBoom.rotation = CC3VectorAdd(_initialCameraRotation, cc3v(pitch, yaw, 0));
}
The pitch is in range [-π, π]. When the device is faced up the pitch = 0 and it becomes π/2 as I take the device from the table and point it to take a picture (portrait mode). The [-π, π] range enables me to rotate the device 360°. When faced down (i.e. device is upside down) the pitch value is π.
The yaw range is only [-π/2, π/2]. It starts at 0 and goes to π/2 when I rotate the device to the left. But if I rotate it beyond π/2, the yaw value starts to decrease.
Can I get the yaw value in range [-π, π], just like the pitch? It would be more useful to be able to rotate the camera sideways by 180° (to the left and to the right, to have a full 360° view) instead of flipping the device vertically to look behind with the camera.