I've been playing with the accelerometer a little and I'm stumped with how to zero-it-out for the current orientation. Here is what I mean:
When you receive messages from UIAccelerometer, you get a nice x, y, z unit vector (more or less) that points towards the gravitational pull given the orientation of your device (or away from it, depending on your philosophical persuasion).
Here is a piece of code that demonstrates that point (just plop it into a layer with CCSprite* _sprite defined):
-(void) accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration {
const float kFilterFactor = 1.0f;
static float prevX=0, prevY=0, prevZ=0;
float accelX = (float) acceleration.x * kFilterFactor + (1- kFilterFactor)*prevX;
float accelY = (float) acceleration.y * kFilterFactor + (1- kFilterFactor)*prevY;
float accelZ = (float) acceleration.z * kFilterFactor + (1- kFilterFactor)*prevZ;
prevX = accelX;
prevY = accelY;
prevZ = accelZ;
// For Landscape orientation, you flip the X and Y with some negation thrown in
_accel = (ccVertex3F) {accelY, -accelX, accelZ};
const float POSITION_SCALE = 100;
_sprite.position = ccp(SCREEN_CENTER_X + _accel.x * POSITION_SCALE,
SCREEN_CENTER_Y + _accel.y * POSITION_SCALE);
_sprite.scale = (_accel.z + 1) * 0.5 * 0.5 + 0.5; // Since _accel.z is a value -1..1, I scale it to 0.5 .. 1
}
This code will place and scale some _sprite such that it appears to orbit around the center of the screen as you rotate your iOS device around.
That's all great, but now I want to re-calibrate the device such that _accel values will behave as if the device was lying flat on a table, whereas in fact I'm lying in bed with the device at an angle and upside down. In other words, I want to take some arbitrary vector in 3 space, treat it as my (0, 0, 1), and rotate whatever value I get back from the accelerometer around this arbitrary vector.
This is where my understanding of trig horribly fails me. How do I do this? I seem to remember something about quaternions and poles, but it's all jumbled inside my noggin.
People must have solved this problem countless number of times, but I can't seem to find a code snippet anywhere. If you have such code and wouldn't mind sharing, please let me know. You'll spare me days of mathematical toil, where I'll just reinvent the wheel and most likely poorly at that.