「VCS/Quaternion4」の編集履歴(バックアップ)一覧に戻る

VCS/Quaternion4 - (2012/12/17 (月) 12:33:00) のソース

|開発環境|Microsoft Visual C# 2010 Express (SP1)|
|実行環境|Microsoft Windows XP Home Edition (SP3)|
|プロジェクトの種類|空のプロジェクト|
|プロジェクト名|Quaternion|

四元数(しげんすう、クォータニオン)の用途には2種類ある。
1.座標を表す。
2.回転軸と角度を表す。

1.の方は値のセットも取得も行う。
2.の方は値をセットし利用はするが、取得はあまり行わない。

***3次元の座標の四元数での表現

ある座標(x,y,z)を四元数で表すには、

 Quaternion p = new Quaternion(new Vector3(x, y, z), 0);

とする。
ちなみに、4番目の要素wをゼロ以外の値にしても問題ないようだが、ゼロ以外にする意味はないと思う。

***回転の四元数での表現

原点を回転の中心として、回転の軸が(x,y,z)で
(右手系の座標定義では、ベクトル(x,y,z)の進む方向に向かって眺めて反時計回りに)
t度回す回転を表す四元数は

 Quaternion q = Quaternion.CreateFromAxisAngle(new Vector3(x, y, z), MathHelper.ToRadians(t));
 Quaternion r = Quaternion.Quaternion.Conjugate(Q);

と作る。(ちなみにrはqの共役四元数という)
回転を実行するには、

 Quaternion rpq = r * p * q;

と計算する。rpqの(x,y,z)が回転した後の座標である。
原点以外を通る回転軸の場合、回転軸が原点を通るように座標を平行移動して回転し、平行移動しなおす。
(もっといい方法があるかもしれない)

参考
-[[四元数で3次元の回転を計算する方法>http://www015.upp.so-net.ne.jp/notgeld/quaternion.html]]
-[[クォータニオンを学んでみよう!>http://marupeke296.com/DXG_No10_Quaternion.html]]
-[[床井研究室 - ゲームグラフィックス特論>http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20040430]]

Program.cs
#highlight(c#){{
// Quaternion4.1
using System;
using Microsoft.Xna.Framework; // .NET参照

class Program
{
    static void Main()
    {
        Vector3 v = new Vector3(0, 1, 0); // 回転軸の方向を表すベクトル
        for (int t = 0; t <= 360; t += 45)
        {
            Quaternion q = Quaternion.CreateFromAxisAngle(v, MathHelper.ToRadians(t));
            Console.Write(string.Format("t={0} / ", t));
            Print(q);
        }
        Console.ReadLine();
    }

    static void Print(Quaternion q)
    {
        Console.WriteLine(string.Format("x={0:f2} y={1:f2} z={2:f2} w={3:f2} len={4:f2}",
            q.X, q.Y, q.Z, q.W, q.Length()));
    }
}
}}

出力
 t=0 / x=0.00 y=0.00 z=0.00 w=1.00 len=1.00
 t=45 / x=0.00 y=0.38 z=0.00 w=0.92 len=1.00
 t=90 / x=0.00 y=0.71 z=0.00 w=0.71 len=1.00
 t=135 / x=0.00 y=0.92 z=0.00 w=0.38 len=1.00
 t=180 / x=0.00 y=1.00 z=0.00 w=0.00 len=1.00
 t=225 / x=0.00 y=0.92 z=0.00 w=-0.38 len=1.00
 t=270 / x=0.00 y=0.71 z=0.00 w=-0.71 len=1.00
 t=315 / x=0.00 y=0.38 z=0.00 w=-0.92 len=1.00
 t=360 / x=0.00 y=0.00 z=0.00 w=-1.00 len=1.00

考察
t=0のときqはQuaternion.Identity(=(0,0,0,1))と同じ値になり無回転を表す。
t=180のときqは(0,1,0)の座標と同じ値であるが、使われ方によってその意味は異なる。

Program.cs
#highlight(c#){{
// Quaternion4.2 任意の回転軸で点を回転
using System;
using Microsoft.Xna.Framework; // .NET参照

class Program
{
    static void Main()
    {
        float a = (float)Math.Sin(MathHelper.ToRadians(45)) * 10;
        Quaternion p = new Quaternion(new Vector3(a, a, 0), 0); // 回転させたい点
        Vector3 v = new Vector3(0, 1, 0); // 回転軸の方向を表すベクトル
        for (int t = 0; t <= 360; t += 45)
        {
            Quaternion q = Quaternion.CreateFromAxisAngle(v, MathHelper.ToRadians(t));
            //Quaternion r = Quaternion.CreateFromAxisAngle(-v, MathHelper.ToRadians(n));
            Quaternion r = Quaternion.Conjugate(q); // 共役。↑と同じ
            Quaternion rpq = r * p * q;
            Console.Write(string.Format("t={0} / ", t));
            Print(rpq);
        }
        Console.ReadLine();
    }

    static void Print(Quaternion q)
    {
        Console.WriteLine(string.Format("x={0:f2} y={1:f2} z={2:f2} w={3:f2} len={4:f2}",
            q.X, q.Y, q.Z, q.W, q.Length()));
    }
}
}}

出力
 t=0 / x=7.07 y=7.07 z=0.00 w=0.00 len=10.00
 t=45 / x=5.00 y=7.07 z=5.00 w=0.00 len=10.00
 t=90 / x=0.00 y=7.07 z=7.07 w=0.00 len=10.00
 t=135 / x=-5.00 y=7.07 z=5.00 w=0.00 len=10.00
 t=180 / x=-7.07 y=7.07 z=0.00 w=0.00 len=10.00
 t=225 / x=-5.00 y=7.07 z=-5.00 w=0.00 len=10.00
 t=270 / x=0.00 y=7.07 z=-7.07 w=0.00 len=10.00
 t=315 / x=5.00 y=7.07 z=-5.00 w=0.00 len=10.00
 t=360 / x=7.07 y=7.07 z=0.00 w=0.00 len=10.00

Program.cs
#highlight(c#){{
// Quaternion4.3 任意の回転軸・原点で点を回転
using System;
using Microsoft.Xna.Framework; // .NET参照

class Program
{
    static void Main()
    {
        Vector3 v = new Vector3(0, 1, 0); // 回転軸の方向を表すベクトル
        Vector3 o = new Vector3(10, 0, 0); // 回転の原点
        Quaternion p = new Quaternion(new Vector3(20, 0, 0) - o, 0); // 回転させたい点-回転の原点
        for (int t = 0; t <= 360; t += 45)
        {
            Quaternion q = Quaternion.CreateFromAxisAngle(v, MathHelper.ToRadians(t));
            //Quaternion r = Quaternion.CreateFromAxisAngle(-v, MathHelper.ToRadians(n));
            Quaternion r = Quaternion.Conjugate(q); // 共役。↑と同じ
            Quaternion rpq = r * p * q;
            Vector3 pos = QV(rpq) + o; // 回転後の点+回転の原点
            Console.Write(string.Format("t={0} / ", t));
            Print(pos);
        }
        Console.ReadLine();
    }

    static void Print(Vector3 v)
    {
        Console.WriteLine(string.Format("x={0:f2} y={1:f2} z={2:f2}", v.X, v.Y, v.Z));
    }

    static Vector3 QV(Quaternion q)
    {
        return new Vector3(q.X, q.Y, q.Z);
    }
}
}}

出力
 t=0 / x=20.00 y=0.00 z=0.00
 t=45 / x=17.07 y=0.00 z=7.07
 t=90 / x=10.00 y=0.00 z=10.00
 t=135 / x=2.93 y=0.00 z=7.07
 t=180 / x=0.00 y=0.00 z=0.00
 t=225 / x=2.93 y=0.00 z=-7.07
 t=270 / x=10.00 y=0.00 z=-10.00
 t=315 / x=17.07 y=0.00 z=-7.07
 t=360 / x=20.00 y=0.00 z=0.00