WisdomSoft - for your serial experiences.

四元数

3次元空間上の軸に対する回転量を四元数を用いて表現できます。

軸と角度

オブジェクトの向きや回転における角度は、一般的な 3DCG ツールでは人間にとって最も直感的なオイラー角が使われています。オイラー角は 3D 空間上の X 軸、Y 軸、Z 軸それぞれの角度を指定することで方向を表します。プログラムでは Vector3 型で表現でき、私たち人間にとって直感的で扱いやすいデータです。しかし、オイラー角にはジンバルロックと呼ばれる難しい問題が付きまといます。

そこで、多くの 3D グラフィックス API と同じように、XNA Framework では四元数を用いて角度を表現します。コードからオブジェクトの角度を指定するには Microsoft.Xna.Framework.Quaternion 構造体を利用する方法が一般的です。

Microsoft.Xna.Framework.Quaternion 構造体
[TypeConverterAttribute("typeof(Microsoft.Xna.Framework.Design.QuaternionConverter)")]
[SerializableAttribute]
public struct Quaternion : IEquatable<Quaternion>

Quaternion 構造体は 1 つの四元数の値を表します。この構造体のコンストラクタは以下のようにオーバーロードされています。

Quaternion 構造体のコンストラクタ
public Quaternion (float x, float y, float z, float w)
public Quaternion (Vector3 vectorPart, float scalarPart)

x パラメータには X 要素の値を、y パラメータには Y 要素の値を、z パラメータには Z 要素の値、w パラメータには W 要素の値を、それぞれ指定します。

コード1
using System.Diagnostics;
using Microsoft.Xna.Framework;

public class TestGame : Game
{
    public static void Main(string[] args)
    {
        Quaternion q1 = new Quaternion();
        Quaternion q2 = new Quaternion(0, 0.3826835F, 0, 0.9238795F);
        Quaternion q3 = new Quaternion(Vector3.Up, -4.371139e-8F);

        Debug.WriteLine("q1=" + q1);
        Debug.WriteLine("q2=" + q2);
        Debug.WriteLine("q3=" + q3);
    }
}
実行結果
コード1 実行結果

コード1はコンストラクタで初期化した Quaternion 構造体の値を出力しています。単にフィールドの値を出力しただけでは四元数の役割を理解することは難しいかもしれませんが、四元数は 3 次元空間でオブジェクトの回転を表すための重要な道具となります。

四元数の各要素はフィールドで公開されています。X 要素の値は X フィールドから、Y 要素の値は Y フィールドから、Z 要素の値は Z フィールドから、W 要素の値は W フィールドから設定または取得できます。

Quaternion 構造体 X フィールド
public float X
Quaternion 構造体 Y フィールド
public float Y
Quaternion 構造体 Z フィールド
public float Z
Quaternion 構造体 W フィールド
public float W

造体のメンバだけを見ると Vector4 構造体との違いがないため Quaternion 構造体の役割に疑問を持つかもしれません。ここで四元数の詳細は割愛しますが、Quaternion 構造体はベクトルではなくベクトルの回転を表現するものであり、その性質は複素数学と深い関係があります。

コード2
using System.Diagnostics;
using Microsoft.Xna.Framework;

public class TestGame : Game
{
    public static void Main(string[] args)
    {
        Quaternion q;
        q.X = 1;
        q.Y = 2;
        q.Z = 3;
        q.W = 4;

        Debug.WriteLine("X=" + q.X + ", Y=" + q.Y + ", Z=" + q.Z + ", W=" + q.W);
    }
}
実行結果
コード2 実行結果

コード2は Quaternion 構造体のフィールドに値を設定し、出力しています。

度とラジアン

一般に、私たちが角度を扱うときは 360 で一周する度数法を用いますが、一般的な数学関数では 2π で一周するラジアン(弧度法)を用います。XNA Framework では、Microsoft.Xna.Framework.MathHelper クラスで基本的な数学処理を行う静的メソッドを提供しており、度とラジアンの変換が可能です。 

Microsoft.Xna.Framework.MathHelper クラス
public static class MathHelper

度をラジアンに変換するには ToRadians() メソッドを、ラジアンを度に変換するには ToDegrees() メソッドを使います。

MathHelper クラス
public static float ToRadians (float degrees)
MathHelper クラス
public static float ToDegrees (float radians)

それぞれ、与えられた角度を指定の単位に変換した値を返します。 

コード3
using System.Diagnostics;
using Microsoft.Xna.Framework;

public class TestGame : Game
{
    public static void Main(string[] args)
    {
        Debug.WriteLine("45°to rad=" + MathHelper.ToRadians(45));
        Debug.WriteLine("90°to rad=" + MathHelper.ToRadians(90));
        Debug.WriteLine("180°to rad=" + MathHelper.ToRadians(180));
        Debug.WriteLine("360°to rad=" + MathHelper.ToRadians(360));
    }
}
実行結果
コード3 実行結果

3D グラフィックス API を用いて物体の向きや回転を制御するときに四元数やラジアン単位での角度が必要になります。