Matrix4x4クラスのメモ

Matrix4x4クラスの基礎知識


マトリックスの並びはRowが行、Columnが列
Mtarix4x4.m行列(mRowColumn)

m00 m01 m02 m03
m10 m11 m12 m13
m20 m21 m22 m23
m30 m31 m32 m33

行列の乗算には可換性がない。つまり A × B ≠ B × A。乗算する順番は重要

<資料>

これは何に使うのか?


行列計算により移動や回転、拡大縮小、投影、射影の計算等を行える
ただし、行列の意味を理解し乗算する順番や各変換の手順を正常に行わないと結果が変わってしまうので色々勉強しておかないと使うのが難しいらしい

Matrix4x4.identity


Matrix4x4.identityは以下のような行列を返す

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

これは「単位行列」と呼ばれる。基礎となる行列

Matrix4x4.identity × A = A
A × Matrix4x4.identity = A になる

行列の作成


マトリクスの作成には様々な手段がある。詳しくはリファレンス参照
手軽に行列を作成するには以下の二つの関数が便利。馴染み深いposition、rotation、scaleを使った作成方法で、このふたつの機能ほとんど同じ


      mat1 = Matrix4x4.identity;
       mat1.SetTRS(new Vector3(1,2,3),Quaternion.identity,new Vector3(1,1,1));
       print(mat1);
結果
1.00000 0.00000 0.00000 1.00000
0.00000 1.00000 0.00000 2.00000
0.00000 0.00000 1.00000 3.00000
0.00000 0.00000 0.00000 1.00000

<他の方法>
マトリックスを直接指定して値を代入。m行列 = 値; で所定の位置に代入できる

      mat1 = Matrix4x4.identity;
       mat1.m03 = 2;
       mat1.m13 = 3;
       mat1.m23 = 4;

1.00000 0.00000 0.00000 2.00000
0.00000 1.00000 0.00000 3.00000
0.00000 0.00000 1.00000 4.00000
0.00000 0.00000 0.00000 1.00000

これ以外に直接マトリックスの配列に値を代入する事も可能

      mat1[0] =1;        //m00
       mat1[1] =2;        //m10
       mat1[2] =3;        //m20
       mat1[3] =4;        //m30
       mat1[4] =5;        //m01
       mat1[5] =6;        //m11
       mat1[6] =7;        //m21
       mat1[7] =8;        //m31
       mat1[8] =9;        //m02
       mat1[9] =10;        //m12
       mat1[10] =11;        //m22
       mat1[11] =12;        //m32
       mat1[12] =13;        //m03
       mat1[13] =14;        //m13
       mat1[14] =15;        //m23
       mat1[15] =16;        //m33

1.00000 5.00000 9.00000 13.00000
2.00000 6.00000 10.00000 14.00000
3.00000 7.00000 11.00000 15.00000
4.00000 8.00000 12.00000 16.00000

等々・・・

変換マトリックスの計算


変換マトリックスを使い座標を計算して返す関数

計算は以下のように行われる
transMat.jpg

<アフィン変換>

x'=m00x + m01y +m02z + m03
y'=m10x + m11y +m12z + m13
z'=m20x + m21y +m22z + m23

P=(x',y',z')=(m00x + m01y +m02z + m03 , m10x + m11y +m12z + m13 , m20x + m21y +m22z + m23)

<サンプル1>
  Matrix4x4 mat2;
   Vector3 answer;
       
   void Start ()
   {
       mat2.m00 = 1;
       mat2.m01 = 2;
       mat2.m02 = 3;
       mat2.m03 = 4;
       mat2.m10 = 5;
       mat2.m11 = 6;
       mat2.m12 = 7;
       mat2.m13 = 8;
       mat2.m20 = 9;
       mat2.m21 = 10;
       mat2.m22 = 11;
       mat2.m23 = 12;
       mat2.m30 = 0;
       mat2.m31 = 0;
       mat2.m32 = 0;
       mat2.m33 = 1;
       
       answer = mat2.MultiplyPoint (new Vector3 (1, 2, 3));
       print(answer);

(18.0 , 46.0 , 74.0) と出力される

計算は以下のように行われている
transMat2.jpg
答えが合っているのが確認できる

変換マトリックスを使った平行移動変換


マトリックス変換を使って(dx,dy,dz)の平行移動をさせたければ
以下のようなマトリックスを作成して

1 0 0 dx
0 1 0 dy
0 0 1 dz
0 0 0 1

行列から位置に変換する
たとえば(1,2,3)にあるものを(2,3,4)だけ平行移動させたければ以下のようなコードになる

  Matrix4x4 mat1;
   Vector3 answer;
   
   void Start () {
       mat1 = Matrix4x4.identity;
       mat1.m03 = 2;
       mat1.m13 = 3;
       mat1.m23 = 4;
       
       answer = mat1.MultiplyPoint3x4(new Vector3(1,2,3));
       print(answer);
   }


(3.0 , 5.0 , 7.0) と出力される

計算を確認すると以下のように行われている
transMat3.jpg

変換マトリックスを使ったスケール変換


マトリックス変換を使って(sx,sy,sz)のスケールを適用させたければ
以下のようなマトリックスを作成して


sx 0 0 0
0 sy 0 0
0 0 sz 0
0 0 0 1


行列から位置に変換する
たとえばあるメッシュオブジェクトを(2,3,4)だけスケーリングさせたければ以下のようなコードになる

  Matrix4x4 mat;
   Vector3[] vertex,afterVertex;
   
   void Start () {
       MeshFilter mf = GetComponent<MeshFilter>();
       vertex = mf.mesh.vertices;
       afterVertex = new Vector3[vertex.Length];

      mat=Matrix4x4.identity;
       mat.m00 = 2;
       mat.m11 = 3;
       mat.m22 = 4;
       
       print(mat);
       
       for (int i = 0; i < vertex.Length; i++) {
               afterVertex[i] = mat.MultiplyPoint3x4(vertex[i]);
       }
       
       mf.mesh.vertices = afterVertex;
   }

これによりメッシュが変形していることが確認できる


メモ


<検索キーワード>
変換行列 変換マトリックス

SimpleSpriteGUI.csは結局、何をしているのか?

  • unityのGUIクラスはGUI.matrixにより変換マトリックスを持っている
これを利用すればpivot位置を持った回転や拡大が可能となる


  • ゲーム動作時の画像解像度
  • 1024×768の場合、画面の中心は512×384になる
unityではScreenクラスで求められる


  • 最終更新:2013-11-04 10:20:47

このWIKIを編集するにはパスワード入力が必要です

認証パスワード