クォータニオン
回転行列の難点
メモリ
回転には3つ(ピッチ、ヨー、ロール)しか自由度がないにも関わらず、回転行列は9つの要素を持つ。
演算コスト
ベクトルと行列の乗算は3つのドット積(9つの乗算と6つの加算)を必要とする。
補間の難しさ
例えば、始点Aから終点Bまでカメラをスムーズに動かす際に、AとBの中間の多数の回転を見つけなければならない。
2つの姿勢が行列で表されていると、その間の指定された割合の回転を見つけることは難しい。
単位クォータニオン
次の制約に従うクォータニオンを単位クォータニオンという。
q=(x,y,z,w)wherex2+y2+z2+w2=1
単位クォータニオンは3次元ベクトルに4番目のスカラー座標をプラスしたものとして、3次元の回転を表すことができる。
- ベクトル部分であるqvは回転の単位軸であり、回転角の半角の正弦でスケールされる
- スカラー部分であるqsは回転角の半角の余弦
q=(qv,qs)=(asin2θ,cos2θ)
aは回転軸に沿った単位ベクトルであり、θは回転角。
回転方向は右手の法則に従うので、親指がaの方向を向いていれば、正の回転は折り曲げた指の方向を向くことになる。
クォータニオンのグラスマン積
2つのクォータニオンpとqがそれぞれ2つの回転PとQを表すとする。
このとき、クォータニオンの積pqは、回転Qの後に回転Pを適用する複合回転を表す。
pq=(pv,ps)(qv,qs)=(pvqs+qvps+pv×qv,psqs−pv⋅qv)
このように定義した積をグラスマン積という。
クォータニオンの共役
クォータニオンpの共役p∗は、ベクトル部分の符号を反転させたものである。
p∗=(−pv,ps)
クォータニオンの逆数
クォータニオンpの逆数はp−1と表し、元のクォータニオンを乗算したときに、スカラーの1となるクォータニオンとして定義する。
pp−1=0i+0j+0k+1=1
最初の3つの成分はsin(0)=0より、最後の成分はcos(0)=1より導かれる。
ところで、sin(−θ)=−sin(θ)であるため、ベクトル部分の符号を反転させたもの(共役)が、逆回転を表すクォータニオンだと考えられる。
数学的には、クォータニオンの逆数は、元のクォータニオンの共役を、元のクォータニオンのノルムの2乗で割ったものとして求められる。
p−1=∣p∣2p∗
3D回転を表すクォータニオンでは、ノルムは常に1であるので、想像通り逆数は共役と等しくなる。
ノルムの計算は2乗での除算というコストが高い処理であるため、それを避けられるのは好都合である。
積の逆数と共役
クォータニオンの積の共役は、個々のクォータニオンの共役の、逆順の積に等しい。
(pq)∗=q∗p∗
同様に、クォータニオンの積の逆数は、個々のクォータニオンの逆数の、逆順の積に等しい。
(pq)−1=q−1p−1
ベクトルを回転させる
ベクトルvに対応するクォータニオンは、ベクトルの成分をベクトル部分に、スカラーの0をスカラー部分に持つクォータニオンである。
v=(vx,vy,vz,0)
ベクトルvをクォータニオンqで回転するためには、次の式を計算する。
rotate(q,v)=qvq−1
クォータニオンは必ず単位長になるので、これはクォータニオンの共役を使うのに等しい。
rotate(q,v)=qvq∗
クォータニオンの連結
クォータニオンq1、q2、q3がそれぞれ回転Q1、Q2、Q3を表すとする。
まず回転Q1を適用した後に回転Q2を適用し、最後に回転Q3を適用したい場合、回転後のベクトルは次のように計算できる。
v′=q3q2q1v(q3q2q1)−1=q3q2q1vq1−1q2−1q3−1
クォータニオンの行列表現
クォータニオンq=(qv,qs)=(x,y,z,w)とすると、回転行列Rは次のように求めることができる。
R=⎝⎛1−2y2−2z22xy+2zw2xz−2yw2xy−2zw1−2x2−2z22yz+2xw2xz+2yw2yz−2xw1−2x2−2y2⎠⎞
回転の線形補間
回転の最も計算量が少ない補間は、4次元ベクトルの線形補間Lerpをクォータニオンに対して実行することである。
2つのクォータニオンqAとqBがそれぞれ回転AとBを表すとすると、次のようにAからBの中間のt%の回転を求めることができる。
lerp(qA,qB,t)=∣qA(1−t)+qBt∣qA(1−t)+qBt=normalize⎝⎛⎝⎛(1−t)qAx+tqBx(1−t)qAy+tqBy(1−t)qAz+tqBz(1−t)qAw+tqBw⎠⎞T⎠⎞
lerp演算は一般的にベクトル長を維持しないため、補間された結果のクォータニオンは再び正規化する必要がある。
回転の球面線形補間
lerpは球面に沿ってではなく、球の弦に沿って補間する。
このため、パラメータtが一定の率で変化しても、一定の角速度を持たない(終点ではゆっくりで、途中では速くなる)回転アニメーションが生まれてしまう。
球面線形補間Slerpは、球面上を一定の角速度で回転するように補間する。
Slerpを求める公式はLerpの公式と同じだが、重み(1−t)とtが、2つのクォータニオンがなす角の正弦を含むwpとwqに置き換えられている。
slerp(qA,qB,t)=wpp+wqq
ここで、
wpwqθ=sin(θ)sin((1−t)θ)=sin(θ)sin(tθ)=cos−1(qA⋅qB)