WisdomSoft - for your serial experiences.

行列

4×4の行列を用いることで平行移動、回転、伸縮などを含む複数の変換を 1 つの値で表現できます。

行列の生成

空間の位置や距離、大きさなどは Vector3 構造体を使い、方向や回転には Quaternion 構造体を使います。これらは、必要最小限の情報量で 3 次元空間のオブジェクトを操作できますが、個別の値として扱わなければなりません。3次元空間上の物体の位置、回転、大きさを 1 つの値として表現することはできません。

複数の変換を 1 つの値として扱うには、4 × 4 の正方行列を用います。線形代数学や幾何学における行列の性質を理解することは重要ですが、プログラミングにおける 4 × 4 の正方行列の実体は、単に 4 × 4 の 2 次元配列にすぎません。XNA Framework の場合、行列は 16 個の float 型要素で構成されます。Vector3 構造体や Quaternion 構造体に比べ情報量が多くなりますが、行列は多くの変換を 1 つの値で記述できるため、計算にとても便利です。

行列は Microsoft.Xna.Framework.Matrix 構造体で表されます。

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

この構造体のコンストラクタはオーバーロードされており、各要素を初期化する値を指定できます。

Matrix 構造体のコンストラクタ
public Matrix (
	float m11, float m12, float m13, float m14,
	float m21, float m22, float m23, float m24,
	float m31, float m32, float m33, float m34,
	float m41, float m42, float m43, float m44
)

m11 パラメータから m44 パラメータまでの 16 個のパラメータには、行列の各要素の値を指定します。

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

public class TestGame : Game
{
    public static void Main(string[] args)
    {
        Matrix m1 = new Matrix();
        Matrix m2 = new Matrix(
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            0, 0, 0, 1
        );

        Debug.WriteLine("m1=" + m1);
        Debug.WriteLine("m2=" + m2);
    }
}
実行結果
コード1 実行結果

コード1は Matrix4x4 構造体の値を生成し、出力しています。m2 変数はコンストラクタで各要素の値を初期化しています。実行結果から、行列の指定した要素が正しく 1 で初期化されていることが確認できます。

行列の各要素はフィールドとして公開されています。M11 フィールドから M44 フィールドまで、規則的に 2 次元配列の添字のような名前で 16 個のフィールドが提供されています。個々の要素を対象に値を設定または取得するには、これらのフィールドを使うとよいでしょう。 

Matrix 構造体 M11 フィールド
public float M11
Matrix 構造体 M44 フィールド
public float M44

これらのフィールドの値を読み書きすることで、生成後の行列の要素を個別に計算できます。

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

public class TestGame : Game
{
    public static void Main(string[] args)
    {
        Matrix m;
        m.M11 = 1;
        m.M22 = 2;
        m.M33 = 3;
        m.M44 = 4;

        Debug.WriteLine("m=" + m);
    }
}
実行結果
コード2 実行結果

コード2は行列の値を生成した後に、行列の各フィールドに値を設定しています。

上記のコードのように、行列の特定のフィールドだけを初期化することが目的であれば、コンストラクタで全ての要素の値を指定するよりも、オブジェクト初期化子を用いて以下のように記述したほうが簡単です。

 Matrix m = new Matrix { M11 = 1, M22 = 2, M33 = 3, M44 = 4 };

コード2に比べ、上記のオブジェクト初期化子を用いたコードの方が短く読みやすいでしょう。

単位行列

単位行列とは正方行列の右下に向かう対角線上の要素が 1、それ以外の要素が 0 の状態の行列を表します。4 × 4 の正方行列である Matrix 構造体においては M11 フィールド、M22 フィールド、M33 フィールド、M44 フィールドの 4 つが 1 で、それ以外のフィールドが 0 の状態の行列です。単位行列は積演算において実数の 1 に相当する値で、任意の行列 a と単位行列の積は常に a となります。

単位行列を取得することが目的であれば Matrix 構造体の静的な Identity プロパティから取得できます。このプロパティは読み取り専用です。

Matrix 構造体 Identity フィールド
public static Matrix Identity { get; }

このプロパティは常に単位行列に等しい Matrix 構造体の値を返します。

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

public class TestGame : Game
{
    public static void Main(string[] args)
    {
        Debug.WriteLine("Identity=" + Matrix.Identity);
    }
}
実行結果
コード3 実行結果

コード3は Identity プロパティが返す単位行列を出力しています。