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


矩陣
矩陣就是一行和列組織起來的矩形數字塊。
矩陣可以理解為是向量的數組。
 
矩陣的維度和記法
矩陣的維度是包含多少行多少列!例如1行2列的矩陣
記法:矩陣m中,對於第1行第2列的元素,我們記為m12
 
方陣
行數和列數相同的矩陣,我們叫做方陣。一般情況下,我們研究的就是2x2, 3x3, 4x4的方陣
 
對角線元素
方陣中,行號和列號相同的元素就是對角線元素,其他的都是非對角線元素。
 
單位矩陣
對角線元素都為1,非對角線元素都為0的矩陣
 
轉置矩陣
對於矩陣M,M的轉置矩陣M T,
M T就是把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();
       }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM