- あなたの場合、デバイスの回転はデバイスの法線の回転に等しいと言えます(法線自体の周りの回転は、指定したように無視されます)
- CMMotionManager.deviceMotionを介して取得できる
CMAttitudeは、参照フレームを基準にした回転を提供します
。そのプロパティのクォータニオン、回転行列、およびオイラー角は、まったく異なる表現です。
- 参照フレームは、CMMotionManagerのstartDeviceMotionUpdatesUsingReferenceFrameメソッドを使用してデバイスモーションの更新を開始するときに指定できます。iOS 4までは、multiplyByInverseOfAttitudeを使用する必要がありました
これをまとめると、デバイスがテーブルに上向きに置かれているときに、クォータニオンに法線ベクトルを正しい方法で乗算する必要があります。ここで、回転を表すこの正しい四元数乗算の方法が必要です。回転ベクトルによると、これは次のように実行されます。
n = q * e * q'ここで、qはCMAttitude [w、(x、y、z)]によって配信されるクォータニオン、q'はその共役[w、(-x、-y、-z)]、eはフェイスアップノーマルのクォータニオン表現[0、(0、0、1)]。残念ながら、AppleのCMQuaternionは構造体であるため、小さなヘルパークラスが必要です。
Quaternion e = [[Quaternion alloc] initWithValues:0 y:0 z:1 w:0];
CMQuaternion cm = deviceMotion.attitude.quaternion;
Quaternion quat = [[Quaternion alloc] initWithValues:cm.x y:cm.y z:cm.z w: cm.w];
Quaternion quatConjugate = [[Quaternion alloc] initWithValues:-cm.x y:-cm.y z:-cm.z w: cm.w];
[quat multiplyWithRight:e];
[quat multiplyWithRight:quatConjugate];
// quat.x, .y, .z contain your normal
Quaternion.h:
@interface Quaternion : NSObject {
double w;
double x;
double y;
double z;
}
@property(readwrite, assign)double w;
@property(readwrite, assign)double x;
@property(readwrite, assign)double y;
@property(readwrite, assign)double z;
Quaternion.m:
- (Quaternion*) multiplyWithRight:(Quaternion*)q {
double newW = w*q.w - x*q.x - y*q.y - z*q.z;
double newX = w*q.x + x*q.w + y*q.z - z*q.y;
double newY = w*q.y + y*q.w + z*q.x - x*q.z;
double newZ = w*q.z + z*q.w + x*q.y - y*q.x;
w = newW;
x = newX;
y = newY;
z = newZ;
// one multiplication won't denormalise but when multipling again and again
// we should assure that the result is normalised
return self;
}
- (id) initWithValues:(double)w2 x:(double)x2 y:(double)y2 z:(double)z2 {
if ((self = [super init])) {
x = x2; y = y2; z = z2; w = w2;
}
return self;
}
クォータニオンは最初は少し奇妙だと思いますが、アイデアが浮かんだら本当に素晴らしいです。これは、四元数をベクトル(x、y、z)の周りの回転として想像するのに役立ち、wは角度(の正弦)です。
それらをさらに活用する必要がある場合は、cocoamathオープンソースプロジェクトをご覧ください。クラスQuaternionとその拡張QuaternionOperationsは、良い出発点です。
完全を期すために、はい、行列の乗算でも実行できます。
n = M * e
しかし、三角法の煩わしさをすべて軽減し、パフォーマンスを向上させるクォータニオン方式をお勧めします。