概要
3次元空間中での回転は、回転軸と回転角で表すことができます。
実用上、回転軸
p
=
(
px ,
py ,
pz
)
と回転角
θ
は、以下のような形式に変換して置くことが多いです。
(
cos
,
sin
p
x ,
sin
p
y ,
sin
p
z
)
これを、以下のように表したりもします。
この形式を四元数といいます。
四元数
四元数なんていうたいそうな名前が付いているは、
元をただせば数学的な意味があるからなんですが、
四元数の数学的意味は、画像処理・3D CG の分野では大して役に立ちません。
応用上は、元々の数学的な意味を知る必要はあまりなく、
回転軸
p
=
(
px ,
py ,
pz
)
と回転角
θ
の情報を、
4次元の単位ベクトルとして、
(
cos
;
sin
p
)
=
(
cos
,
sin
p
x ,
sin
p
y ,
sin
p
z
)
という形式で持っているものとだけ覚えておけば十分。
3次元空間上の回転
まず、3次元空間上の回転を定式化します。
3次元空間上の回転を表すためには、回転軸ベクトル
p
と回転角度 θが必要になります。
回転軸ベクトルの絶対値は意味を持たないので、
|
p
|
=
1
であるものとしてます。
座標ベクトル
u
で表される点 A を、回転軸
p
を中心に角度 θ 回転した点 A' の座標ベクトル
u'
は、以下のような計算で求めることができます。
u'
=
sinθ u
×
p
+
cosθ (
u
−
(
u
⋅
p
)
p
)
+
(
u
⋅
p
)p
=
sinθ u
×
p
+
cosθ
u
+
(
1 − cosθ
)
(
u
⋅
p
)
p
ちなみに、この式の導出の仕方ですが、下図のようになります。

3次元ベクトルの回転
原点を O、点 A から回転軸におろした垂線の足を H とすると、
OH
=
(
u
⋅
p
)
p
HA
=
u
−
(
u
⋅
p
)
p
となります。
また
u
×
p
は、
p
および
HA
に垂直で、
絶対値が
|
HA
|
と等しいベクトルになります。
HA'
は、
HA' = cosθ HA + sinθ u×p
=
sinθ u
×
p
+
cosθ
u
+
(
1 − cosθ
)
(
u
⋅
p
)
p
と表すことができるので、先ほど示した式を導き出すことができます。
行列を使った3次元空間上の回転
前節で示した式で3次元空間中の回転が表現できるんですが、
実際には、この式をそのまま使うのではなく、行列演算に変形してから使います。
(行列にすることで、拡大縮小や平行移動などと一緒に、まとめて扱えるため。)
3次元ベクトルの外積計算は以下のように、
p
×
u
<span class="normal">=</span>
<span class="vector">u</span>
<span class="paren" style="font-size:4em;">[</span><div data-ufcpp-raw-table-placeholder="12"></div><span class="paren" style="font-size:4em;">]</span>
</div>
行列とベクトルの積としても書き表わせます。
(ただし、ベクトルは横ベクトルを仮定しています。)
また、
(
u
⋅
p
)
p
という部分も、
(
u
⋅
p
)
p
<span class="normal">=</span>
<span class="vector">u</span>
<span class="paren" style="font-size:4em;">[</span><div data-ufcpp-raw-table-placeholder="13"></div><span class="paren" style="font-size:4em;">]</span>
</div>
と表せます。
これらを使うと、
先ほどの回転の式は、以下のような行列で表すことができます。
u'
=
sinθ u
×
p
+
cosθ
u
+
(
1 − cosθ
)
(
u
⋅
p
)
p
=
cosθ
u
<span class="normal">+</span>
<span class="paren" style="font-size:em;">(</span>
<span class="normal">1</span> <span class="normal">−</span> <span class="normal">cos</span>θ
<span class="paren" style="font-size:em;">)</span>
<span class="vector">u</span>
<span class="paren" style="font-size:4em;">[</span><div data-ufcpp-raw-table-placeholder="14"></div><span class="paren" style="font-size:4em;">]</span>
<span class="normal">+</span>
<span class="normal">sin</span>θ
<span class="vector">u</span>
<span class="paren" style="font-size:4em;">[</span><div data-ufcpp-raw-table-placeholder="15"></div><span class="paren" style="font-size:4em;">]</span>
</div><div class="math">
<span class="normal">=</span>
<span class="vector">u</span>
<span class="paren" style="font-size:4em;">[</span><div data-ufcpp-raw-table-placeholder="16"></div><span class="paren" style="font-size:4em;">]</span>
</div>
四元数から回転行列を計算
ここで話を四元数に戻します。
四元数は、
回転軸
p
=
(
px ,
py ,
pz
)
と回転角
θ
の情報を、以下の形式で保持するものです。
(
cos
;
sin
p
)
=
(
cos
,
sin
p
x ,
sin
p
y ,
sin
p
z
)
ここで、sin や cos を何度も書きたくないので、
以下のように書き表わすことにします。
q
=
(
q
w ,
q
x ,
q
y ,
q
z ,
)
=
(
cos
,
sin
p
x ,
sin
p
y ,
sin
p
z
)
ここで、三角関数の倍角の公式を使うと、以下の等式が導かれます。
(* と † の位置には、
x, y, z のいずれかが入ります。)
2
q
*
q
†
<span class="normal">=</span>
<span class="normal">2</span>
<span class="normal">sin</span><sup><span class="normal">2</span></sup>
<div data-ufcpp-raw-table-placeholder="27"></div>
p<sub>*</sub>
p<sub>
<span class="normal">†</span>
</sub>
<span class="normal">=</span>
<span class="paren" style="font-size:em;">(</span>
<span class="normal">1</span> <span class="normal">−</span> <span class="normal">cos</span>θ
<span class="paren" style="font-size:em;">)</span>
p<sub>*</sub>
p<sub>
<span class="normal">†</span>
</sub>
</div><div class="math">
<span class="normal">2</span>
q<sub>w</sub>
q<sub>*</sub>
<span class="normal">=</span>
<span class="normal">2</span>
<span class="normal">sin</span>
<div data-ufcpp-raw-table-placeholder="28"></div>
<span class="normal">cos</span>
<div data-ufcpp-raw-table-placeholder="29"></div>
p<sub>*</sub>
<span class="normal">=</span>
<span class="normal">sin</span>θ
p<sub>*</sub>
</div><div class="math">
<span class="normal">2</span>
q<sub>w</sub><sup><span class="normal">2</span></sup>
<span class="normal">=</span>
<span class="normal">2</span>
<span class="normal">cos</span><sup><span class="normal">2</span></sup>
<div data-ufcpp-raw-table-placeholder="30"></div>
<span class="normal">=</span>
<span class="normal">1</span>
<span class="normal">+</span>
<span class="normal">cos</span>θ
</div>
これらを、前節で求めた行列に代入すると、
以下の結果が得られます。
u'
=
u
<span class="paren" style="font-size:4em;">[</span><div data-ufcpp-raw-table-placeholder="31"></div><span class="paren" style="font-size:4em;">]</span>
</div>
あるいは、
|
q
|
=
1
なことを利用して、以下のようにも書けます。
u'
=
u
[|
1
−
2
(
qy2
+
qz2
)
|
2
(
qx
qy
−
qz
qw
)
|
2
(
qx
qz
+
qy
qw
)
|
|
2
(
qx
qy
+
qz
qw
)
|
1
−
2
(
qz2
+
qx2
)
|
2
(
qy
qz
−
qx
qw
)
|
|
2
(
qx
qy
−
qy
qw
)
|
2
(
qy
qz
+
qx
qw
)
|
1
−
2
(
qx2
+
qy2
)
|
]
ちなみに、こうやって作られた行列は、必ず直交行列になります。
(実際、計算してみてもらうと、各列が正規直行していることがわかります。)
回転しかしていないんだから、長さも角度も変わらない変換(= 直交行列による1次変換)になっていないとおかしいはずです。