http://www-sens.sys.es.osaka-u.ac.jp/users/kanaya/Documents/VCQ/kanaya-handai-quaternion.pdf
を勉強してみたところ、クオータニオンの積は、2つの回転を含むベクトルの合成であると書いてある。クオータニオン L, R, Res を適当に取り、Res = L * R を図解すると、下の図のように、クオータニオン L の軸に対して、クオータニオン Rののベクトルを、クオータニオン Lの回転角度だけ回転したものが クオータニオン Res となる。
右項のクオータニオンの回転が0の場合は上の絵のように回転面に対して、右項Rを回転させるだけでわかりやすいが、右項のクオータニオンの回転が0ではない場合に、Rにさらに回転が加わったものに対して、左項のクオータニオンの回転が合成されるため、先の資料を読んでいても、よくわからない。
そこで、XAML でプログラムを作って、実際に動作を確かめてみた。Form 左のスライダーが、左項クオータニオンの X, Y, Z, W、右側のスライダーが 右項のクオータニオンの X, Y, Z, W。ピンクのベクトルが 左項のクオータニオン、黄色のベクトルが右項のクオータニオン、黒のベクトルが積のクオータニオン。スライダーで、左項、右項のクオータニオンを動かすと、結果としての積のクオータニオンを表示するWPFアプリケーション。
スライダーの値を読み取って、クオータニオンの積を計算し、表示する処理の一部抜粋。
private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
try
{
// 左項
Vector3D leftAxis = new Vector3D(lx.Value, ly.Value, lz.Value);
Quaternion leftQuaternion = new Quaternion(leftAxis, lrot.Value);
QuaternionRotation3D qrot3d = new QuaternionRotation3D(leftQuaternion);
RotateTransform3D leftRot3D = new RotateTransform3D(qrot3d);
Transform3DGroup leftT3DG = (Transform3DGroup)(this.LeftOR23.Transform);
leftT3DG.Children[2] = leftRot3D;
this.LeftOR23.Transform = leftT3DG;
this.textBlock1.Text = “Left:”
+ lx.Value.ToString(“f2”) + “:”
+ ly.Value.ToString(“f2”) + “:”
+ lz.Value.ToString(“f2”) + “:”
+ lrot.Value.ToString(“f2”);
// 右項
Vector3D rightAxis = new Vector3D(rx.Value, ry.Value, rz.Value);
Quaternion rightQuaternion = new Quaternion(rightAxis, rrot.Value);
QuaternionRotation3D rightQRot3D = new QuaternionRotation3D(rightQuaternion);
RotateTransform3D rightRot3D = new RotateTransform3D(rightQRot3D);
Transform3DGroup rightT3DG = (Transform3DGroup)(this.RightOR26.Transform);
rightT3DG.Children[2] = rightRot3D;
this.RightOR26.Transform = rightT3DG;
this.textBlock1.Text += “\nRight:”
+ rx.Value.ToString(“f2”) + “:”
+ ry.Value.ToString(“f2”) + “:”
+ rz.Value.ToString(“f2”) + “:”
+ rrot.Value.ToString(“f2”);
// クオータニオンの積
Quaternion resultQuaternion = leftQuaternion * rightQuaternion;
QuaternionRotation3D resultQR3D = new QuaternionRotation3D(resultQuaternion);
RotateTransform3D resultRot3D = new RotateTransform3D(resultQR3D);
Transform3DGroup resultTr = (Transform3DGroup)(this.ResultOR29.Transform);
resultTr.Children[2] = resultRot3D;
this.ResultOR29.Transform = resultTr;
this.textBlock1.Text += “\nResult:”
+ resultQuaternion.X.ToString(“f2”) + “:”
+ resultQuaternion.Y.ToString(“f2”) + “:”
+ resultQuaternion.Z.ToString(“f2”) + “:”
+ resultQuaternion.W.ToString(“f2”);
}
catch
{
}
}
これで、スライダーを動かして確かめてみると・・・なるほど・・・こうなるのか・・・。
これを数式から読み取るのは不可能だな・・・・・
こんな3次元のモデルも XAML で簡単にできてしまうあたりに感動してしまった。
ということで、回転させたい対象のクオータニオンをR、回転させる軸と回転角度を表わすクオータニオンLとすると、回転後のクオータニオン RES = L*R でとても簡単に計算ができる。ここで求められた回転後のクオータニオンRESから、RotateTransform3D を回転させたい対象に適用してあげれば、回転してくれるということだ。
クオータニオンがなければ、マトリックス計算の地獄になるところだけれど、クオータニオンの積一発。おまけに、WPF は、このクオータニオンの積も提供してくれているので、とても処理が楽。素晴らしい。