初音ミク XAML化計画~初音ミクをグリングリンするには、ベクトルの外積とクオータニオン

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 となる。

image 

右項のクオータニオンの回転が0の場合は上の絵のように回転面に対して、右項Rを回転させるだけでわかりやすいが、右項のクオータニオンの回転が0ではない場合に、Rにさらに回転が加わったものに対して、左項のクオータニオンの回転が合成されるため、先の資料を読んでいても、よくわからない。

そこで、XAML でプログラムを作って、実際に動作を確かめてみた。Form 左のスライダーが、左項クオータニオンの X, Y, Z, W、右側のスライダーが 右項のクオータニオンの X, Y, Z, W。ピンクのベクトルが 左項のクオータニオン、黄色のベクトルが右項のクオータニオン、黒のベクトルが積のクオータニオン。スライダーで、左項、右項のクオータニオンを動かすと、結果としての積のクオータニオンを表示するWPFアプリケーション。

image

スライダーの値を読み取って、クオータニオンの積を計算し、表示する処理の一部抜粋。

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 は、このクオータニオンの積も提供してくれているので、とても処理が楽。素晴らしい。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です