1. 程式人生 > >Unity3D學習筆記(三十三):矩陣

Unity3D學習筆記(三十三):矩陣

轉置 pda atime private art mesh fir render 旋轉矩陣

矩陣 矩陣就是一行和列組織起來的矩形數字塊。 矩陣可以理解為是向量的數組。 矩陣的維度和記法 矩陣的維度是包含多少行多少列!例如1行2列的矩陣 記法:矩陣m中,對於第1行第2列的元素,我們記為m12 方陣 行數和列數相同的矩陣,我們叫做方陣。一般情況下,我們研究的就是2x2, 3x3, 4x4的方陣 對角線元素 方陣中,行號和列號相同的元素就是對角線元素,其他的都是非對角線元素。 單位矩陣 對角線元素都為1,非對角線元素都為0的矩陣 轉置矩陣 對於矩陣M,M的轉置矩陣MT, MT就是把M的行變為列,把M的列變成行 向量和矩陣 行向量:一行幾列的矩陣 列向量:幾行一列的矩陣 矩陣的運算: 標量和矩陣的乘法: M = m11 m12 * 2 = 2*m11 2*m12 m21 m22 2*m21 2*m22 矩陣中的每一個元素都與這個標量相乘,最終結果還是一個矩陣。 矩陣與矩陣相乘: 矩陣和矩陣的乘法,並不是什麽形式都可以,必須讓左邊矩陣的列和右邊矩陣的行保持一致,否則不能相乘。 矩陣與矩陣相乘的結果:還是一個矩陣,該矩陣的行數是左邊矩陣的行數,該矩陣的列數就是右邊矩陣的列數。 矩陣與矩陣相乘,不滿足乘法交換律。 技術分享圖片
對於結果矩陣中的Cij Cij = 左邊矩陣的第i行的每個元素與右邊矩陣的第j列的每個元素相乘的和。 技術分享圖片
13 12 -3 10
4 0 -1 22
-8 6 5 5

a b c d f
g h i j k

k 0
0 k 

技術分享圖片

1x-3 + -2x4, 1x7 + -2x1/3
5x-3 + 0x4, 5x7 + 0x1/3

3x-2 + -1x0 + 4x3, 3x0 + -1x7 + 4x-4, 3x3 + -1x-6 + 4x2,

2x2 + 3x5 +4x3, 2x3 + 3x7 +4x4, 2x1 + 3x2 +4x5
2x2 + 7x5 +10x3, 2x3 + 7x7 +10x4, 2x1 + 7x2 +10x5
向量和矩陣的乘法 行向量:放在矩陣的左側進行乘運算,左乘矩陣 列向量:放在矩陣的右側進行乘運算,右乘矩陣 對於同一個向量同一個矩陣,這個向量左乘矩陣的結果,與右乘矩陣的結果不一致! 矩陣的幾何意義: 對於給定的向量a,矩陣M,有aM = b,,那麽我們可以說M將a轉換到了b,那麽一個向量乘以一個矩陣相當於做了一次坐標變換。 描述一個物體變換時的規律。 其中包括:旋轉,縮放,投影,鏡像等。 線性變換:從幾何上來理解:變換前是直線,變換後依舊是直線,變換前是幾何原點,那麽變換後依舊是幾何原點。如3x3 仿射變換:線性變換 + 平移,如4x4 矩陣的行列式(只存在於方陣中) 行列式不是矩陣,是一個標量(就是數)f 方陣的行列式:|M| 或 detM 二階方陣的行列式的計算: 技術分享圖片

三階方陣的行列式的計算:

技術分享圖片

2 3 1
3 2 3
7 5 8

2x2x8+ 3x5x1 + 7x3x3 
-2x5x3 - 3x3x8 - 7x2x1

2 3
4 5

2x5 - 3x4
代數余子式: 代數余子式是數,對於n階方陣,代數余子式:n*n個 對於n階方陣中的每個元素都有一個代數余子式。 Cij = 去掉了第i行第j列,剩下的矩陣的行列式 * -1的 i+j 次冪。 技術分享圖片
矩陣
2 4 5
3 4 1
5 3 2

C11 =(4x2 - 3x1 ) x (-1)(1+1)
C12 =(3x2 - 5x1 ) x (-1)(1+2)
C13 =(3x3 - 5x4 ) x (-1)(1+3)
C21 =(4x2 - 3x5 ) x (-1)(2+1)
C22 =(2x2 - 5x5 ) x (-1)(2+2)
C23 =(2x3 - 5x4 ) x (-1)(2+3)
C31 =(4x1 - 4x5 ) x (-1)(3+1)
C32 =(2x1 - 3x5 ) x (-1)(3+2)
C33 =(2x4 - 3x4 ) x (-1)(3+3)

5 -1  -11
7 -21 14
-16 -13 -4
標準伴隨矩陣 對於矩陣M,M的標準伴隨矩陣記做adjM adjM = 就是M矩陣的代數余子式組成矩陣的轉置矩陣。 矩陣的逆: 方陣的M的逆,記做:M-1 對於矩陣來說,並不是所有的矩陣都有逆矩陣。 如果一個矩陣的行列式不為0,證明這個矩陣是由逆矩陣,可逆的。 如果一個矩陣的行列式為0,證明這個矩陣是不可逆的。 對於一個有逆矩陣的矩陣來說,我們叫做該矩陣是可逆的或非奇異的。 對於一個沒有逆矩陣的矩陣來說,該矩陣是不可逆的或奇異的。 逆矩陣 = 標準伴隨矩陣 / 矩陣的行列式 求逆矩陣: 1.求矩陣的行列式,判斷矩陣是否可逆 2.求矩陣的標準伴隨矩陣(代數余子式組成矩陣的轉置矩陣) 3.求逆矩陣
矩陣
2 5
7 10

矩陣的行列式
|M| = 20 - 35 = -15

標準伴隨矩陣
10 -7
-5 2

轉置矩陣
10 -5
-7 2

逆矩陣
-2/3 1/3
7/15 -2/15 

矩陣
1 2 1
3 2 1
1 1 2

矩陣的行列式
|M| = 4+2+3 -2-12-1 = -6

標準伴隨矩陣
3 -5 1
-3 1 1
0 2 -4

轉置矩陣
3 -3 0
-5 1 2
1 1 -4

逆矩陣
-1/2 1/2 0
5/6 -1/6 -1/3
-1/6 -1/6 2/3
逆矩陣的幾何意義:對於M矩陣實現的變換,M的逆矩陣表示的就是相反的變換。 旋轉矩陣: 技術分享圖片 X‘ = (Cosθ,Sinθ) Y‘ = (-Sinθ,Cosθ) 2D旋轉變換的矩陣 組成矩陣 Cosθ Sinθ -Sinθ Cosθ 如果旋轉角為45度 0.707 0.707 -0.707 0.707 對於坐標(1, 0) 0.707 0.707 -0.707 0.707 * (1, 0) = (0.707,0.707),代表繞著Z軸旋轉45度的變換 3D旋轉變換的矩陣 繞X軸旋轉的矩陣(左乘): 1 0 0 0 Cosθ Sinθ 0 -Sinθ Cosθ 繞Y軸旋轉的矩陣 Cosθ 0 -Sinθ 0 1 0 Sinθ 0 Cosθ 繞Z軸旋轉的矩陣 Cosθ Sinθ 0 -Sinθ Cosθ 0 0 0 1 (1, 2, 0),繞Z軸旋轉30度 0.866 0.5 0 -0.5 0.866 0 0 0 1 x = 1x0.866 + 2x-5 + 0x0 = y = 1x0.5 + 2x0.866 + 0x0 = z = 1x0 + 2x0 + 0x1 = 縮放矩陣: 對於給定的向量(X, Y),縮放X軸縮放Sx倍,Y軸縮放Sy倍 最終結果是(X*Sx, Y*Sy) m11 m12 (X, Y) * m21 m22 → X1 = X*m11 + Y*m21 Y1 = X*m12 + Y*m22 → X1 = X*Sx Y1 = Y*Sy → X*Sx= X*m11 + Y*m21 Y*Sy= X*m12 + Y*m22 → m11 = Sx m12 = 0 m21 = 0 m22 = Sy 最終的2D的縮放矩陣 Sx 0 0 Sy 最終的3D的縮放矩陣 Sx 0 0 0 Sy 0 0 0 Sz Sx 對應的是X的值的縮放系數 Sy 對應的是Y的值的縮放系數 Sz 對應的是Z的值的縮放系數 縮放系數為1的時候,表示沒有縮放 投影矩陣: 對於XY的投影矩陣(把Z的坐標變為0,其他兩個不變) 1 0 0 0 1 0 0 0 0 對於XZ平面的投影矩陣 1 0 0 0 0 0 0 0 1 對於YZ平面的投影矩陣 0 0 0 0 1 0 0 0 1 鏡像矩陣: 對於以YZ平面鏡像的矩陣 -1 0 0 0 1 0 0 0 1 對於以XZ平面鏡像的矩陣 1 0 0 0 -1 0 0 0 1 對於以XY平面鏡像的矩陣 1 0 0 0 1 0 0 0 -1 平移: 對於給定向量(x, y, z)平移一個(x‘, y‘, z‘)的向量的位置 對於向量表示方向:(x, y, z) 對於向量表示坐標:(x+x‘, y+y‘, z+z‘) m11 m12 m13 (x, y, z) * m21 m22 m23 m31 m32 m33 X1 = X*m11 + Y*m21 + Z*m31 Y1 = X*m12 + Y*m22 + Z*m32 Z1 = X*m13 + Y*m23 + Z*m33 三維坐標不能表示平移 齊次坐標 (x, y, z)從三維的矢量變成四維(x, y, z, w) 當 w = 1 時,證明 x, y, z 表示的是點 當 w = 0 時,證明 x, y, z 表示的是方向 m11 m12 m13 m14 (x, y, z) * m21 m22 m23 m24 m31 m32 m33 m34 m41 m42 m43 m44 X1 = X*m11 + Y*m21 + Z*m31 + W*m41 Y1 = X*m12 + Y*m22 + Z*m32 + W*m42 Z1 = X*m13 + Y*m23 + Z*m33 + W*m43 W1 = X*m14 + Y*m24 + Z*m34 + W*m44 X1 = X*m11 + Y*m21 + Z*m31 + W*m41 = x + x‘ → m11=1; m21=0; m31=0; m41=x‘; Y1 = X*m12 + Y*m22 + Z*m32 + W*m42 = y + y‘ → m12=0; m22=1; m32=0; m42=y‘; Z1 = X*m13 + Y*m23 + Z*m33 + W*m43 = z + z‘ → m13=0; m23=0; m33=1; m43=z‘; W1 = X*m14 + Y*m24 + Z*m34 + W*m44 = w → m14=0; m24=0; m34=0; m44=1; 使用 4x4 的矩陣表示三維向量的平移(左乘矩陣) 1 0 0 0 0 1 0 0 0 0 1 0 x‘ y‘ z‘ 1 這是平移的左乘矩陣 使用 4x4 的矩陣表示三維向量的旋轉 繞Z軸旋轉 Cosθ Sinθ 0 0 -Sinθ Cosθ 0 0 0 0 1 0 0 0 0 1 復合變換: Cosθ Sinθ 0 0 -Sinθ Cosθ 0 0 0 0 1 0 x‘ y‘ z‘ 1 對於(0, 0, 0)這個點,沿著x軸平移1個單位,再繞著z軸旋轉90度 先平移再旋轉的結果(0, 1, 0) 先旋轉再平移的結果(1, 0, 0) 0 1 0 0 -1 0 0 0 0 0 1 0 (0, 0, 0, 1) * -1 0 0 1 = (1, 0, 0, 1) 旋轉 * 平移 = 復合變化(復合變換要註意順序) Cosθ Sinθ 0 0 1 0 0 0 Cosθ Sinθ 0 0 -Sinθ Cosθ 0 0 0 1 0 0 -Sinθ Cosθ 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 * x‘ y‘ z‘ 1 = x‘ y‘ z‘ 1 案例-動態生成網格 技術分享圖片
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CreateMesh : MonoBehaviour 
{
       void Start () {


        MeshFilter mf = gameObject.AddComponent<MeshFilter>();
        MeshRenderer mr = gameObject.AddComponent<MeshRenderer>();


        //先實例化一個網格
        Mesh mesh = new Mesh();


        //確定網格的四個頂點
        //先創建一個Vector3類型的數組
        Vector3[] vertexs = new Vector3[4];
        vertexs[0] = new Vector3(-1, 1, 0);
        vertexs[1] = new Vector3(1, 1, 0);
        vertexs[2] = new Vector3(-1, -1, 0);
        vertexs[3] = new Vector3(1, -1, 0);


        //把頂點給mesh
        mesh.vertices = vertexs;


        //再確定頂點組成三角面的順序,註意數組的數量一定是3的倍數
        //因為3個頂點才能組成1個三角面,註意三角面的頂點的順序,順時針在正面,逆時針在反面
        int[] triangles = new int[] {0,1,2,1,3,2};
        mesh.triangles = triangles;


        //最終把網格給MeshFilter
        mf.mesh = mesh;
    }
}

技術分享圖片

using UnityEngine;
using System.Collections;
public class buildMesh : MonoBehaviour {


       public Vector3 vertLeftTopFront = new Vector3(-1,1,1);
       public Vector3 vertRightTopFront = new Vector3(1,1,1);
       public Vector3 vertRightTopBack = new Vector3(1,1,-1);
       public Vector3 vertLeftTopBack = new Vector3(-1,1,-1);
       private float waitN = 3f;
       private float waitD = 3f;
       public int shapeN = 0;

       void Start () 
       {
              MeshFilter mf = GetComponent<MeshFilter>();
              Mesh mesh = mf.mesh;


              //Vertices//
              Vector3[] vertices = new Vector3[]
              {
                     //front face//
                     vertLeftTopFront,//left top front, 0
                     vertRightTopFront,//right top front, 1
                     new Vector3(-1,-1,1),//left bottom front, 2
                     new Vector3(1,-1,1),//right bottom front, 3
                     //back face//
                     vertRightTopBack,//right top back, 4
                     vertLeftTopBack,//left top back, 5
                     new Vector3(1,-1,-1),//right bottom back, 6
                     new Vector3(-1,-1,-1),//left bottom back, 7
                     //left face//
                     vertLeftTopBack,//left top back, 8
                     vertLeftTopFront,//left top front, 9
                     new Vector3(-1,-1,-1),//left bottom back, 10
                     new Vector3(-1,-1,1),//left bottom front, 11
                     //right face//
                     vertRightTopFront,//right top front, 12
                     vertRightTopBack,//right top back, 13
                     new Vector3(1,-1,1),//right bottom front, 14
                     new Vector3(1,-1,-1),//right bottom back, 15
                     //top face//
                     vertLeftTopBack,//left top back, 16
                     vertRightTopBack,//right top back, 17
                     vertLeftTopFront,//left top front, 18
                     vertRightTopFront,//right top front, 19
                     //bottom face//
                     new Vector3(-1,-1,1),//left bottom front, 20
                     new Vector3(1,-1,1),//right bottom front, 21
                     new Vector3(-1,-1,-1),//left bottom back, 22
                     new Vector3(1,-1,-1)//right bottom back, 23
              };


              //Triangles// 3 points, clockwise determines which side is visible
              int[] triangles = new int[]
              {
                     //front face//
                     0,2,3,//first triangle
                     3,1,0,//second triangle
                     //back face//
                     4,6,7,//first triangle
                     7,5,4,//second triangle
                     //left face//
                     8,10,11,//first triangle
                     11,9,8,//second triangle
                     //right face//
                     12,14,15,//first triangle
                     15,13,12,//second triangle
                     //top face//
                     16,18,19,//first triangle
                     19,17,16,//second triangle
                     //bottom face//
                     20,22,23,//first triangle
                     23,21,20//second triangle
              };


              //UVs//
              Vector2[] uvs = new Vector2[]
              {
                     //front face// 0,0 is bottom left, 1,1 is top right//
                     new Vector2(0,1),
                     new Vector2(0,0),
                     new Vector2(1,1),
                     new Vector2(1,0),
                     new Vector2(0,1),
                     new Vector2(0,0),
                     new Vector2(1,1),
                     new Vector2(1,0),
                     new Vector2(0,1),
                     new Vector2(0,0),
                     new Vector2(1,1),
                     new Vector2(1,0),
                     new Vector2(0,1),
                     new Vector2(0,0),
                     new Vector2(1,1),
                     new Vector2(1,0),
                     new Vector2(0,1),
                     new Vector2(0,0),
                     new Vector2(1,1),
                     new Vector2(1,0),
                     new Vector2(0,1),
                     new Vector2(0,0),
                     new Vector2(1,1),
                     new Vector2(1,0)
              };


              mesh.Clear ();
              mesh.vertices = vertices;
              mesh.triangles = triangles;
              mesh.uv = uvs;
              ;
              mesh.RecalculateNormals();
       
       }
       
       void Update () 
       {
              if(waitN > 0f)
              {
                     waitN -= Time.deltaTime;
              }
              else
              {
                     waitN = waitD;
                     shapeN ++;
                     if(shapeN > 3)
                     {
                           shapeN = 0;
                     }
              }
              //morph to cube//
              if(shapeN == 0)
              {
                     vertLeftTopFront = Vector3.Lerp(vertLeftTopFront, new Vector3(-1,1,1),Time.deltaTime);
                     vertRightTopFront = Vector3.Lerp(vertRightTopFront, new Vector3(1,1,1),Time.deltaTime);
                     vertRightTopBack = Vector3.Lerp(vertRightTopBack, new Vector3(1,1,-1),Time.deltaTime);
                     vertLeftTopBack = Vector3.Lerp(vertLeftTopBack, new Vector3(-1,1,-1),Time.deltaTime);
              }
              //morph to pyramid//
              if(shapeN == 1)
              {
                     vertLeftTopFront = Vector3.Lerp(vertLeftTopFront, new Vector3(0,1,0),Time.deltaTime);
                     vertRightTopFront = Vector3.Lerp(vertRightTopFront, new Vector3(0,1,0),Time.deltaTime);
                     vertRightTopBack = Vector3.Lerp(vertRightTopBack, new Vector3(0,1,0),Time.deltaTime);
                     vertLeftTopBack = Vector3.Lerp(vertLeftTopBack, new Vector3(0,1,0),Time.deltaTime);
              }
              //morph to ramp//
              if(shapeN == 2)
              {
                     vertLeftTopFront = Vector3.Lerp(vertLeftTopFront, new Vector3(-1,-1,2),Time.deltaTime);
                     vertRightTopFront = Vector3.Lerp(vertRightTopFront, new Vector3(1,-1,2),Time.deltaTime);
                     vertRightTopBack = Vector3.Lerp(vertRightTopBack, new Vector3(1,0.5f,-1),Time.deltaTime);
                     vertLeftTopBack = Vector3.Lerp(vertLeftTopBack, new Vector3(-1,0.5f,-1),Time.deltaTime);
              }
              //morph to roof//
              if(shapeN == 3)
              {
                     vertLeftTopFront = Vector3.Lerp(vertLeftTopFront, new Vector3(-1,0.2f,0),Time.deltaTime);
                     vertRightTopFront = Vector3.Lerp(vertRightTopFront, new Vector3(1,0.2f,0),Time.deltaTime);
                     vertRightTopBack = Vector3.Lerp(vertRightTopBack, new Vector3(1,0.2f,0),Time.deltaTime);
                     vertLeftTopBack = Vector3.Lerp(vertLeftTopBack, new Vector3(-1,0.2f,0),Time.deltaTime);
              }
              Start();
       }
}

Unity3D學習筆記(三十三):矩陣