2010-07-24 (土)
*[Android] SensorManager.getRotationMatrix で得た回転行列の使い方
そのままOpenGLで使う場合と,getOrientation()でヨー,ピッチ,ロール角をそれぞれ求める方法があります.まずは,そのまま使ってみる.
getRotationMatrix で取得した回転行列はfloatの1次元配列に格納されます.常識的に考えれば行列型であるべきですが,Javaで行列型を作ってもまったく便利でないばかりか,面倒が増える上に負荷が増えるだけなのは目に見えているので単純なfloat配列なのは合理的な判断なんでしょう.
SDKを見ると,
M[ 0] M[ 1] M[ 2] M[ 3] M[ 4] M[ 5] M[ 6] M[ 7] M[ 8] M[ 9] M[10] M[11] M[12] M[13] M[14] M[15]
という形で入る用です.OpenGLの行列を直に扱ったことのある人はこれ見ると,行と列を入れ替えないといけないのか…と少しがっかりしてしまいますが,そんなことはちゃんと考えられているようで,SDKに直接OpenGLで使って大丈夫だよと書いてあります.
行と列が入れ替わってしまっているのでOpenGLには転置行列として扱われます.良く考えれば,そもそもMは単なる回転行列なので,転置すると逆行列になります.そして,デバイスの回転の逆行列ということはOpenGLでそのまま使った場合物体を本来見える位置に移動するのに使えます.
そのとおりなんだけど…ちゃんと分かってないと危ないんじゃないかな.
さらに,なんでglMultMatrixfにoffsetあるの?と思ったけど,javaって複製せずに部分配列を渡す手段が無いのか.酷いな.
次に,getOrientationを使ってみます.
float[] inR = new float[16]; float[] outR = new float[16]; float[] I = new float[16]; float[] orientation = new float[3]; SensorManager.getRotationMatrix(inR, I, accel, magnet); SensorManager.remapCoordinateSystem(inR, SensorManager.AXIS_X, SensorManager.AXIS_Z, outR); SensorManager.getOrientation(outR, orientation);
getRotationMatrixで取得した行列をremapCoordinateSystemで,画面の座標系に直します.このとき,画面上のXY軸を現実世界の座標にどう対応するか指定します.画面を横向きや逆さにしたりしている場合は,このままだと直感的でなくなるので,軸の向きを変えないといけません.
あとは,getOrientationで回転角が取得できます.
- orientation[0] 方位(Z軸周り) 北向きが0
- orientation[1] 仰角(X軸周り) 水平方向が0
- orientation[2] ロール角(Y軸周り) 普通の状態が0
最初に使った行列もそうですが,空を向くベクトルがZ,方角の基準は北になっています.