精华内容
下载资源
问答
  • 如果a和b是两个矩阵的话,a*b是进行矩阵相乘,a.*b是a矩阵的每个元素乘以b矩阵对应位置的元素形成的个新矩阵,一般两个矩阵运算使用点乘,如下图所示:第步我们来看一下例子,在matlab命令行窗口中输入a=[1 2;...

    https://jingyan.baidu.com/article/b907e6276e5c6e46e6891c79.html

    第一步我们首先需要知道,如果a和b是两个矩阵的话,a*b是进行矩阵相乘,a.*b是a矩阵的每一个元素乘以b矩阵对应位置的元素形成的一个新矩阵,一般两个矩阵运算使用点乘,如下图所示:

    c554baf187a9204bca8d86962f166df2.png

    1. 第二步我们来看一下例子,在matlab命令行窗口中输入a=[1 2;2 4],b=[1 5;3 6],创建a和b两个矩阵,如下图所示:

    53129472589a293846ab918a8a81e737.png

    1. 第三步在命令行窗口中输入a*b,可以看到是两个矩阵相乘的结果,如下图所示:

    ed33457db7028eee9023c376656d2426.png

    1. 第四步输入a.*b,按回车键之后,可以看到是两个矩阵每个对应位置元素相乘形成的一个新矩阵,如下图所示:

    0e1a8cd9851e0f3f92a625f44e7a9513.png

    1. 第五步最后我们可以看一下矩阵乘以数值的结果,也是每个元素乘以数值形成的新矩阵,矩阵乘数值和矩阵点乘数值的结果是一样的,如下图所示:

    9857957ebc8008ec6c2b65506d961001.png

    The result of "dot multiplication" between a matrix and a number is as same as the result of multiplying a matrix by a number.

    3040b040265b2617f6c2d0c85a46a58b.png
    展开全文
  • )首先,无论dx还是...()在明确了这一点后,然后我们再看“矩阵的存储方式”,矩阵存储方式有两种,种是“主序(row-major order)/优先”,另种就是“主序(column-major order)/优先” 1)D

    (一)首先,无论dx还是opengl,所表示的矢量和矩阵都是依据线性代数中的标准定义的:
    “矩阵A与B的乘积矩阵C的第i行第j列的元素c(ij)等于A的第i行于B的第j列的对应元素乘积的和。”(实用数学手册,科学出版社,第二版)
    例如c12 = a11*b11+a12*b21+a12*b13...

    (二)在明确了这一点后,然后我们再看“矩阵的存储方式”,矩阵存储方式有两种,一种是“行主序(row-major order)/行优先”,另一种就是“列主序(column-major order)/列优先”
    1)Direct3D 采用行主序存储

    “Effect matrix parameters and HLSL matrix variables can define whether the value is a row-major or column-major matrix; however, the DirectX APIs always treat D3DMATRIX and D3DXMATRIX as row-major.”(见d3d9 document/Casting and Conversion 一节)
    2)OpenGL 采用列主序存储
    “The m parameter points to a 4x4 matrix of single- or double-precision floating-point values stored in column-major order. That is, the matrix is stored as follows”
    (见msdn glLoadMatrixf API说明)

    存储顺序说明了线性代数中的矩阵如何在线性的内存数组中存储,d3d 将每一行在数组中按行存储,而opengl将每一列存储到数组的每一行中:
          线性代数意义的同一个矩阵,在d3d 和 ogl 中却有不同的存储顺序
                  线代:a11,a12,a13,a14               d3d :  a11,a12,a13,a14                   gl: a11,a21,a31,a41
                           a21,a22,a23,a24                         a21,a22,a23,a24                       a12,a22,a32,a42
                           a31,a32,a33,a34                         a31,a32,a33,a34                       a13,a23,a33,a43
                           a41,a42,a43,a44                         a41,a42,a43,a44                       a14,a24,a34,a44

    (三)矩阵乘法顺序和规则

    矩阵乘法在线性代数中的定义是确定的,然而在不同的实现中出现了“左乘”和“右乘”的区别,或者叫做“前乘(pre-multiply),后乘(post-multiply)”
    这个规则取决于vector的表示形式,即行向量还是列向量。如果是行向量,其实就是一个行矩阵。那么表示线性代数意义的“行x列”,就是前乘。矩阵乘法也是如此。
    如d3d中,
                            

                                  

    D3D 是行向量,行优先存储,OpenGL是列向量,列优先存储。同一个矩阵用D3D存储还是用opengl存储虽然不同,但是变换的结果却是相同,
    因为opengl 变换向量是把向量视作列向量,并同矩阵的每一列相乘,用来实现线性代数中同一个变换。

    我们通常很难看到opengl变换坐标的代码,以下代码出自opengl source code,让我们一窥顶点变换的“庐山真面目”

    void FASTCALL __glXForm3(__GLcoord *res, const __GLfloat v[3], const __GLmatrix *m)
    {
        __GLfloat x = v[0];
        __GLfloat y = v[1];
        __GLfloat z = v[2];

        res->x = x*m->matrix[0][0] + y*m->matrix[1][0] + z*m->matrix[2][0]
     + m->matrix[3][0];
        res->y = x*m->matrix[0][1] + y*m->matrix[1][1] + z*m->matrix[2][1]
     + m->matrix[3][1];
        res->z = x*m->matrix[0][2] + y*m->matrix[1][2] + z*m->matrix[2][2]
     + m->matrix[3][2];
        res->w = x*m->matrix[0][3] + y*m->matrix[1][3] + z*m->matrix[2][3]
     + m->matrix[3][3];
    }

    可见确实如上所述,“OPENGL列向量和矩阵的每一列相乘,仍然表示线性代数行向量和矩阵的每一行相乘”
    再来看一下opengl 矩阵相乘,“用a的每一列去乘b的每一行”。

    /*
    ** Compute r = a * b, where r can equal b.
    */
    void FASTCALL __glMultMatrix(__GLmatrix *r, const __GLmatrix *a, const __GLmatrix *b)
    {
        __GLfloat b00, b01, b02, b03;
        __GLfloat b10, b11, b12, b13;
        __GLfloat b20, b21, b22, b23;
        __GLfloat b30, b31, b32, b33;
        GLint i;

        b00 = b->matrix[0][0]; b01 = b->matrix[0][1];
            b02 = b->matrix[0][2]; b03 = b->matrix[0][3];
        b10 = b->matrix[1][0]; b11 = b->matrix[1][1];
            b12 = b->matrix[1][2]; b13 = b->matrix[1][3];
        b20 = b->matrix[2][0]; b21 = b->matrix[2][1];
            b22 = b->matrix[2][2]; b23 = b->matrix[2][3];
        b30 = b->matrix[3][0]; b31 = b->matrix[3][1];
            b32 = b->matrix[3][2]; b33 = b->matrix[3][3];

        for (i = 0; i < 4; i++) {
     r->matrix[i][0] = a->matrix[i][0]*b00 + a->matrix[i][1]*b10
         + a->matrix[i][2]*b20 + a->matrix[i][3]*b30;
     r->matrix[i][1] = a->matrix[i][0]*b01 + a->matrix[i][1]*b11
         + a->matrix[i][2]*b21 + a->matrix[i][3]*b31;
     r->matrix[i][2] = a->matrix[i][0]*b02 + a->matrix[i][1]*b12
         + a->matrix[i][2]*b22 + a->matrix[i][3]*b32;
     r->matrix[i][3] = a->matrix[i][0]*b03 + a->matrix[i][1]*b13
         + a->matrix[i][2]*b23 + a->matrix[i][3]*b33;

     

     

    1。矩阵和线性变换:一一对应

    矩阵是用来表示线性变换的一种工具,它和线性变换之间是一一对应的。
    考虑线性变换:
    a11*x1 + a12*x2 + ...+a1n*xn = x1'
    a21*x1 + a22*x2 + ...+a2n*xn = x2'
    ...
    am1*x1 + am2*x2 + ...+amn*xn = xm'

    对应地,用矩阵来表示就是:
    |a11 a12 ... a1n   |   |x1|     |x1'|
    |a21 a22 ... a2n   |   |x2|     |x2'|
    |...                      |* |...|=    |... |
    |am1 am2 ... amn |   |xn|     |xm'|

    也可以如下来表示:
                       |a11 a21 ... am1|
                       |a12 a22 ... am2|  
    |x1 x2...xn|*|...                   |= |x1' x2'... xm'|      
                       |a1n a2n ... amn|

    其中涉及到6个矩阵。分别为A[m*n],X[n*1],X'[m*1]以及X[1*n],A[n*m],X'[1*m]。
    可以理解成向量x(x1,x2,...,xn)经过一个变换矩阵A[m*n]或A[n*m]后变成另外一个向量x'(x1',x2',...,xm'))。

    2。矩阵的表示法:行矩阵 vs. 列矩阵

    行矩阵和列矩阵的叫法是衍生自行向量和列向量。
    其实,矩阵A[m*n]可以看成是m个n维的row vector构成的row matrix,也可看成是n个m维的column vector构成的column matrix。
    其中,X[n*1]/X'[m*1]就等价于1个n/m维的column vector。X[1*n]/X'[1*m]就等价于1个n/m维的row vector。
    Row matrix和Column matrix只是两种不同的表示法,前者表示把一个向量映射到矩阵的一行,后者表示把一个向量映射到矩阵的一列。
    本质上体现的是同一线性变换。矩阵运算规定了它们可以通过转置运算来改变这个映射关系。

    3。矩阵的相乘顺序:前乘或左乘 vs. 后乘或右乘

    需要注意的是两种不同的表示法对应不同的运算顺序:
    如果对一个column vector做变换,则变换矩阵(row matrix/vectors)必须出现在乘号的左边,即pre-multiply,又叫前乘或左乘。
    如果对一个row vector做变换,则变换矩阵(column matrix/vectors)必须出现在乘号的右边,即post-multiply,又叫后乘或右乘。
    一般不会弄错,因为矩阵乘法性质决定了相同的内维数的矩阵才能相乘。至于为什么是这个规律,为什么要row vector乘以column vector或column vector乘以row vector???想想吧。。。

    所以左乘还是右乘,跟被变换的vector的表示形式相关,而非存储顺序决定。

    4。矩阵的存储顺序:按行优先存储 vs. 按列优先存储

    涉及到在计算机中使用矩阵时,首先会碰到存储矩阵的问题。
    因为计算机存储空间是先后有序的,如何存储A[m*n]的m*n个元素是个问题,一般有两种:按行优先存储和按列优先存储。

    row-major:存成a11,a12,...,amn的顺序。
    column-major:存成a11,a21,...,amn的顺序。

    这样问题就来了,给你一个存储好的矩阵元素集合,你不知道如何读取元素组成一个矩阵,比如你不知道a12该放在几行几列上。
    所以,每个系统都有自己的规定,比如以什么规则存储的就以什么规则读取。DX使用Row-major,OGL使用Column-major.即一个相同的矩阵A[m*n]在DX和OGL中的存储序列是不一样的,这带来了系统间转换的麻烦。

    不过,一个巧合的事情是:DX中,点/向量是用Row Vector来表示的,所以对应的变换矩阵是Column Matrix/Vectors,而OGL中,点/向量是用Column Vector来表示的,所以对应的变换矩阵是Row Matrix/Vectors.所以,如果在DX中对一个向量x(x1,x2,x3,1)或点(x(x1,x2,x3,1))应用A[4*4]的矩阵变换,就是x' = x(x1,x2,x3,1) * A[4*4],由于采用Row-major,所以它的存储序列是a11,a12,...,a43,a44。在OGL中,做同样的向量或点的变换,因为其使用Row Matrix/Vectors,其应用的变换矩阵应该是A'[4*4] = A[4*4]( ' 表示Transpose/转置),就是x' = A'[4*4] * x'(x1,x2,x3,1),但是由于采用Column-major,它的存储序列正好也是a11,a12,...,a43,a44!!!
    所以实际上,对DX和OGL来讲,同一个变换,存储的矩阵元素序列是一样的.比如:都是第13,14,15个元素存储了平移变化量deltaZ,deltaY,deltaZ.

    Refs:
    http://mathworld.wolfram.com/Matrix.html
    http://www.gamedev.net/community/forums/topic.asp?topic_id=321862

    展开全文
  • )首先,无论dx还是opengl,所表示的矢量和矩阵都是依据线性代数中的标准定义的:“矩阵A与B的乘积矩阵C的第i第j的元素c(ij)等于A的第i于B的第j的对应元素乘积的和。”(实用数学手册,科学出版社,第...

    [转载]http://www.xuebuyuan.com/882848.html

    (一)首先,无论dx还是opengl,所表示的矢量和矩阵都是依据线性代数中的标准定义的:
    “矩阵A与B的乘积矩阵C的第i行第j列的元素c(ij)等于A的第i行于B的第j列的对应元素乘积的和。”(实用数学手册,科学出版社,第二版)
    例如c12 = a11*b11+a12*b21+a12*b13...

    (二)在明确了这一点后,然后我们再看“矩阵的存储方式”,矩阵存储方式有两种,一种是“行主序(row-major order)/行优先”,另一种就是“列主序(column-major order)/列优先”
    1)Direct3D 采用行主序存储

    “Effect matrix parameters and HLSL matrix variables can define whether the value is a row-major or column-major matrix; however, the DirectX APIs always treat D3DMATRIX and D3DXMATRIX as row-major.”(见d3d9 document/Casting and Conversion 一节)
    2)OpenGL 采用列主序存储
    “The m parameter points to a 4x4 matrix of single- or double-precision floating-point values stored in column-major order. That is, the matrix is stored as follows”
    (见msdn glLoadMatrixf API说明)

    存储顺序说明了线性代数中的矩阵如何在线性的内存数组中存储,d3d 将每一行在数组中按行存储,而opengl将每一列存储到数组的每一行中:
          线性代数意义的同一个矩阵,在d3d 和 ogl 中却有不同的存储顺序
                  线代:a11,a12,a13,a14               d3d :  a11,a12,a13,a14                   gl: a11,a21,a31,a41
                           a21,a22,a23,a24                         a21,a22,a23,a24                       a12,a22,a32,a42
                           a31,a32,a33,a34                         a31,a32,a33,a34                       a13,a23,a33,a43
                           a41,a42,a43,a44                         a41,a42,a43,a44                       a14,a24,a34,a44

    (三)矩阵乘法顺序和规则

    矩阵乘法在线性代数中的定义是确定的,然而在不同的实现中出现了“左乘”和“右乘”的区别,或者叫做“前乘(pre-multiply),后乘(post-multiply)”
    这个规则取决于vector的表示形式,即行向量还是列向量。如果是行向量,其实就是一个行矩阵。那么表示线性代数意义的“行x列”,就是前乘。矩阵乘法也是如此。
    如d3d中,
                            

                                  

    D3D 是行向量,行优先存储,OpenGL是列向量,列优先存储。同一个矩阵用D3D存储还是用opengl存储虽然不同,但是变换的结果却是相同,
    因为opengl 变换向量是把向量视作列向量,并同矩阵的每一列相乘,用来实现线性代数中同一个变换。

    我们通常很难看到opengl变换坐标的代码,以下代码出自opengl source code,让我们一窥顶点变换的“庐山真面目”

    void FASTCALL __glXForm3(__GLcoord *res, const __GLfloat v[3], const __GLmatrix *m)
    {
        __GLfloat x = v[0];
        __GLfloat y = v[1];
        __GLfloat z = v[2];

        res->x = x*m->matrix[0][0] + y*m->matrix[1][0] + z*m->matrix[2][0]
     + m->matrix[3][0];
        res->y = x*m->matrix[0][1] + y*m->matrix[1][1] + z*m->matrix[2][1]
     + m->matrix[3][1];
        res->z = x*m->matrix[0][2] + y*m->matrix[1][2] + z*m->matrix[2][2]
     + m->matrix[3][2];
        res->w = x*m->matrix[0][3] + y*m->matrix[1][3] + z*m->matrix[2][3]
     + m->matrix[3][3];
    }

    可见确实如上所述,“OPENGL列向量和矩阵的每一列相乘,仍然表示线性代数行向量和矩阵的每一行相乘”
    再来看一下opengl 矩阵相乘,“用a的每一列去乘b的每一行”。

    /*
    ** Compute r = a * b, where r can equal b.
    */
    void FASTCALL __glMultMatrix(__GLmatrix *r, const __GLmatrix *a, const __GLmatrix *b)
    {
        __GLfloat b00, b01, b02, b03;
        __GLfloat b10, b11, b12, b13;
        __GLfloat b20, b21, b22, b23;
        __GLfloat b30, b31, b32, b33;
        GLint i;

        b00 = b->matrix[0][0]; b01 = b->matrix[0][1];
            b02 = b->matrix[0][2]; b03 = b->matrix[0][3];
        b10 = b->matrix[1][0]; b11 = b->matrix[1][1];
            b12 = b->matrix[1][2]; b13 = b->matrix[1][3];
        b20 = b->matrix[2][0]; b21 = b->matrix[2][1];
            b22 = b->matrix[2][2]; b23 = b->matrix[2][3];
        b30 = b->matrix[3][0]; b31 = b->matrix[3][1];
            b32 = b->matrix[3][2]; b33 = b->matrix[3][3];

        for (i = 0; i < 4; i++) {
     r->matrix[i][0] = a->matrix[i][0]*b00 + a->matrix[i][1]*b10
         + a->matrix[i][2]*b20 + a->matrix[i][3]*b30;
     r->matrix[i][1] = a->matrix[i][0]*b01 + a->matrix[i][1]*b11
         + a->matrix[i][2]*b21 + a->matrix[i][3]*b31;
     r->matrix[i][2] = a->matrix[i][0]*b02 + a->matrix[i][1]*b12
         + a->matrix[i][2]*b22 + a->matrix[i][3]*b32;
     r->matrix[i][3] = a->matrix[i][0]*b03 + a->matrix[i][1]*b13
         + a->matrix[i][2]*b23 + a->matrix[i][3]*b33;

     

     

    1。矩阵和线性变换:一一对应

    矩阵是用来表示线性变换的一种工具,它和线性变换之间是一一对应的。
    考虑线性变换:
    a11*x1 + a12*x2 + ...+a1n*xn = x1'
    a21*x1 + a22*x2 + ...+a2n*xn = x2'
    ...
    am1*x1 + am2*x2 + ...+amn*xn = xm'

    对应地,用矩阵来表示就是:
    |a11 a12 ... a1n   |   |x1|     |x1'| 
    |a21 a22 ... a2n   |   |x2|     |x2'|
    |...                      |* |...|=    |... |
    |am1 am2 ... amn |   |xn|     |xm'|

    也可以如下来表示:
                       |a11 a21 ... am1| 
                       |a12 a22 ... am2|  
    |x1 x2...xn|*|...                   |= |x1' x2'... xm'|      
                       |a1n a2n ... amn| 

    其中涉及到6个矩阵。分别为A[m*n],X[n*1],X'[m*1]以及X[1*n],A[n*m],X'[1*m]。
    可以理解成向量x(x1,x2,...,xn)经过一个变换矩阵A[m*n]或A[n*m]后变成另外一个向量x'(x1',x2',...,xm'))。

    2。矩阵的表示法:行矩阵 vs. 列矩阵

    行矩阵和列矩阵的叫法是衍生自行向量和列向量。
    其实,矩阵A[m*n]可以看成是m个n维的row vector构成的row matrix,也可看成是n个m维的column vector构成的column matrix。
    其中,X[n*1]/X'[m*1]就等价于1个n/m维的column vector。X[1*n]/X'[1*m]就等价于1个n/m维的row vector。
    Row matrix和Column matrix只是两种不同的表示法,前者表示把一个向量映射到矩阵的一行,后者表示把一个向量映射到矩阵的一列。
    本质上体现的是同一线性变换。矩阵运算规定了它们可以通过转置运算来改变这个映射关系。

    3。矩阵的相乘顺序:前乘或左乘 vs. 后乘或右乘

    需要注意的是两种不同的表示法对应不同的运算顺序:
    如果对一个column vector做变换,则变换矩阵(row matrix/vectors)必须出现在乘号的左边,即pre-multiply,又叫前乘或左乘。
    如果对一个row vector做变换,则变换矩阵(column matrix/vectors)必须出现在乘号的右边,即post-multiply,又叫后乘或右乘。
    一般不会弄错,因为矩阵乘法性质决定了相同的内维数的矩阵才能相乘。至于为什么是这个规律,为什么要row vector乘以column vector或column vector乘以row vector???想想吧。。。

    所以左乘还是右乘,跟被变换的vector的表示形式相关,而非存储顺序决定。

    4。矩阵的存储顺序:按行优先存储 vs. 按列优先存储

    涉及到在计算机中使用矩阵时,首先会碰到存储矩阵的问题。
    因为计算机存储空间是先后有序的,如何存储A[m*n]的m*n个元素是个问题,一般有两种:按行优先存储和按列优先存储。

    row-major:存成a11,a12,...,amn的顺序。
    column-major:存成a11,a21,...,amn的顺序。

    这样问题就来了,给你一个存储好的矩阵元素集合,你不知道如何读取元素组成一个矩阵,比如你不知道a12该放在几行几列上。
    所以,每个系统都有自己的规定,比如以什么规则存储的就以什么规则读取。DX使用Row-major,OGL使用Column-major.即一个相同的矩阵A[m*n]在DX和OGL中的存储序列是不一样的,这带来了系统间转换的麻烦。

    不过,一个巧合的事情是:DX中,点/向量是用Row Vector来表示的,所以对应的变换矩阵是Column Matrix/Vectors,而OGL中,点/向量是用Column Vector来表示的,所以对应的变换矩阵是Row Matrix/Vectors.所以,如果在DX中对一个向量x(x1,x2,x3,1)或点(x(x1,x2,x3,1))应用A[4*4]的矩阵变换,就是x' = x(x1,x2,x3,1) * A[4*4],由于采用Row-major,所以它的存储序列是a11,a12,...,a43,a44。在OGL中,做同样的向量或点的变换,因为其使用Row
    Matrix/Vectors,其应用的变换矩阵应该是A'[4*4] = A[4*4]( ' 表示Transpose/转置),就是x' = A'[4*4] * x'(x1,x2,x3,1),但是由于采用Column-major,它的存储序列正好也是a11,a12,...,a43,a44!!!
    所以实际上,对DX和OGL来讲,同一个变换,存储的矩阵元素序列是一样的.比如:都是第13,14,15个元素存储了平移变化量deltaZ,deltaY,deltaZ.

    Refs:

    http://mathworld.wolfram.com/Matrix.html

    http://www.gamedev.net/community/forums/topic.asp?topic_id=321862

    转载于:https://www.cnblogs.com/peeno/p/5952207.html

    展开全文
  • )首先,无论dx还是opengl,所表示的矢量和矩阵都是依据线性代数中的标准定义的: “矩阵A与B的乘积矩阵C的第i...()在明确了这一点后,然后我们再看“矩阵的存储方式”,矩阵存储方式有两种,种是“主序

    (一)首先,无论dx还是opengl,所表示的矢量和矩阵都是依据线性代数中的标准定义的:
    “矩阵A与B的乘积矩阵C的第i行第j列的元素c(ij)等于A的第i行于B的第j列的对应元素乘积的和。”(实用数学手册,科学出版社,第二版)
    例如c12 = a11*b11+a12*b21+a12*b13...

    (二)在明确了这一点后,然后我们再看“矩阵的存储方式”,矩阵存储方式有两种,一种是“行主序(row-major order)/行优先”,另一种就是“列主序(column-major order)/列优先”
    1)Direct3D 采用行主序存储

    “Effect matrix parameters and HLSL matrix variables can define whether the value is a row-major or column-major matrix; however, the DirectX APIs always treat D3DMATRIX and D3DXMATRIX as row-major.”(见d3d9 document/Casting and Conversion 一节)
    2)OpenGL 采用列主序存储
    “The m parameter points to a 4x4 matrix of single- or double-precision floating-point values stored in column-major order. That is, the matrix is stored as follows”
    (见msdn glLoadMatrixf API说明)

    存储顺序说明了线性代数中的矩阵如何在线性的内存数组中存储,d3d 将每一行在数组中按行存储,而opengl将每一列存储到数组的每一行中:
          线性代数意义的同一个矩阵,在d3d 和 ogl 中却有不同的存储顺序
                  线代:a11,a12,a13,a14               d3d :  a11,a12,a13,a14                   gl: a11,a21,a31,a41
                           a21,a22,a23,a24                         a21,a22,a23,a24                       a12,a22,a32,a42
                           a31,a32,a33,a34                         a31,a32,a33,a34                       a13,a23,a33,a43
                           a41,a42,a43,a44                         a41,a42,a43,a44                       a14,a24,a34,a44

    (三)矩阵乘法顺序和规则

    矩阵乘法在线性代数中的定义是确定的,然而在不同的实现中出现了“左乘”和“右乘”的区别,或者叫做“前乘(pre-multiply),后乘(post-multiply)”
    这个规则取决于vector的表示形式,即行向量还是列向量。如果是行向量,其实就是一个行矩阵。那么表示线性代数意义的“行x列”,就是前乘。矩阵乘法也是如此。
    如d3d中,
                           

                                  

    D3D 是行向量,行优先存储,OpenGL是列向量,列优先存储。同一个矩阵用D3D存储还是用opengl存储虽然不同,但是变换的结果却是相同,
    因为opengl 变换向量是把向量视作列向量,并同矩阵的每一列相乘,用来实现线性代数中同一个变换。

    我们通常很难看到opengl变换坐标的代码,以下代码出自opengl source code,让我们一窥顶点变换的“庐山真面目”

    void FASTCALL __glXForm3(__GLcoord *res, const __GLfloat v[3], const __GLmatrix *m)
    {
        __GLfloat x = v[0];
        __GLfloat y = v[1];
        __GLfloat z = v[2];

        res->x = x*m->matrix[0][0] + y*m->matrix[1][0] + z*m->matrix[2][0]
     + m->matrix[3][0];
        res->y = x*m->matrix[0][1] + y*m->matrix[1][1] + z*m->matrix[2][1]
     + m->matrix[3][1];
        res->z = x*m->matrix[0][2] + y*m->matrix[1][2] + z*m->matrix[2][2]
     + m->matrix[3][2];
        res->w = x*m->matrix[0][3] + y*m->matrix[1][3] + z*m->matrix[2][3]
     + m->matrix[3][3];
    }

    可见确实如上所述,“OPENGL列向量和矩阵的每一列相乘,仍然表示线性代数行向量和矩阵的每一行相乘”
    再来看一下opengl 矩阵相乘,“用a的每一列去乘b的每一行”。

    /*
    ** Compute r = a * b, where r can equal b.
    */
    void FASTCALL __glMultMatrix(__GLmatrix *r, const __GLmatrix *a, const __GLmatrix *b)
    {
        __GLfloat b00, b01, b02, b03;
        __GLfloat b10, b11, b12, b13;
        __GLfloat b20, b21, b22, b23;
        __GLfloat b30, b31, b32, b33;
        GLint i;

        b00 = b->matrix[0][0]; b01 = b->matrix[0][1];
            b02 = b->matrix[0][2]; b03 = b->matrix[0][3];
        b10 = b->matrix[1][0]; b11 = b->matrix[1][1];
            b12 = b->matrix[1][2]; b13 = b->matrix[1][3];
        b20 = b->matrix[2][0]; b21 = b->matrix[2][1];
            b22 = b->matrix[2][2]; b23 = b->matrix[2][3];
        b30 = b->matrix[3][0]; b31 = b->matrix[3][1];
            b32 = b->matrix[3][2]; b33 = b->matrix[3][3];

        for (i = 0; i < 4; i++) {
     r->matrix[i][0] = a->matrix[i][0]*b00 + a->matrix[i][1]*b10
         + a->matrix[i][2]*b20 + a->matrix[i][3]*b30;
     r->matrix[i][1] = a->matrix[i][0]*b01 + a->matrix[i][1]*b11
         + a->matrix[i][2]*b21 + a->matrix[i][3]*b31;
     r->matrix[i][2] = a->matrix[i][0]*b02 + a->matrix[i][1]*b12
         + a->matrix[i][2]*b22 + a->matrix[i][3]*b32;
     r->matrix[i][3] = a->matrix[i][0]*b03 + a->matrix[i][1]*b13
         + a->matrix[i][2]*b23 + a->matrix[i][3]*b33;

     

     

    1。矩阵和线性变换:一一对应

    矩阵是用来表示线性变换的一种工具,它和线性变换之间是一一对应的。
    考虑线性变换:
    a11*x1 + a12*x2 + ...+a1n*xn = x1'
    a21*x1 + a22*x2 + ...+a2n*xn = x2'
    ...
    am1*x1 + am2*x2 + ...+amn*xn = xm'

    对应地,用矩阵来表示就是:
    |a11 a12 ... a1n   |   |x1|     |x1'|
    |a21 a22 ... a2n   |   |x2|     |x2'|
    |...                      |* |...|=    |... |
    |am1 am2 ... amn |   |xn|     |xm'|

    也可以如下来表示:
                       |a11 a21 ... am1|
                       |a12 a22 ... am2|  
    |x1 x2...xn|*|...                   |= |x1' x2'... xm'|      
                       |a1n a2n ... amn|

    其中涉及到6个矩阵。分别为A[m*n],X[n*1],X'[m*1]以及X[1*n],A[n*m],X'[1*m]。
    可以理解成向量x(x1,x2,...,xn)经过一个变换矩阵A[m*n]或A[n*m]后变成另外一个向量x'(x1',x2',...,xm'))。

    2。矩阵的表示法:行矩阵 vs. 列矩阵


    行矩阵和列矩阵的叫法是衍生自行向量和列向量。
    其实,矩阵A[m*n]可以看成是m个n维的row vector构成的row matrix,也可看成是n个m维的column vector构成的column matrix。
    其中,X[n*1]/X'[m*1]就等价于1个n/m维的column vector。X[1*n]/X'[1*m]就等价于1个n/m维的row vector。
    Row matrix和Column matrix只是两种不同的表示法,前者表示把一个向量映射到矩阵的一行,后者表示把一个向量映射到矩阵的一列。
    本质上体现的是同一线性变换。矩阵运算规定了它们可以通过转置运算来改变这个映射关系。

    3。矩阵的相乘顺序:前乘或左乘 vs. 后乘或右乘


    需要注意的是两种不同的表示法对应不同的运算顺序:
    如果对一个column vector做变换,则变换矩阵(row matrix/vectors)必须出现在乘号的左边,即pre-multiply,又叫前乘或左乘。
    如果对一个row vector做变换,则变换矩阵(column matrix/vectors)必须出现在乘号的右边,即post-multiply,又叫后乘或右乘。
    一般不会弄错,因为矩阵乘法性质决定了相同的内维数的矩阵才能相乘。至于为什么是这个规律,为什么要row vector乘以column vector或column vector乘以row vector???想想吧。。。

    所以左乘还是右乘,跟被变换的vector的表示形式相关,而非存储顺序决定。

    4。矩阵的存储顺序:按行优先存储 vs. 按列优先存储

    涉及到在计算机中使用矩阵时,首先会碰到存储矩阵的问题。
    因为计算机存储空间是先后有序的,如何存储A[m*n]的m*n个元素是个问题,一般有两种:按行优先存储和按列优先存储。

    row-major:存成a11,a12,...,amn的顺序。
    column-major:存成a11,a21,...,amn的顺序。

    这样问题就来了,给你一个存储好的矩阵元素集合,你不知道如何读取元素组成一个矩阵,比如你不知道a12该放在几行几列上。
    所以,每个系统都有自己的规定,比如以什么规则存储的就以什么规则读取。DX使用Row-major,OGL使用Column-major.即一个相同的矩阵A[m*n]在DX和OGL中的存储序列是不一样的,这带来了系统间转换的麻烦。

    不过,一个巧合的事情是:DX中,点/向量是用Row Vector来表示的,所以对应的变换矩阵是Column Matrix/Vectors,而OGL中,点/向量是用Column Vector来表示的,所以对应的变换矩阵是Row Matrix/Vectors.所以,如果在DX中对一个向量x(x1,x2,x3,1)或点(x(x1,x2,x3,1))应用A[4*4]的矩阵变换,就是x' = x(x1,x2,x3,1) * A[4*4],由于采用Row-major,所以它的存储序列是a11,a12,...,a43,a44。在OGL中,做同样的向量或点的变换,因为其使用Row Matrix/Vectors,其应用的变换矩阵应该是A'[4*4] = A[4*4]( ' 表示Transpose/转置),就是x' = A'[4*4] * x'(x1,x2,x3,1),但是由于采用Column-major,它的存储序列正好也是a11,a12,...,a43,a44!!!
    所以实际上,对DX和OGL来讲,同一个变换,存储的矩阵元素序列是一样的.比如:都是第13,14,15个元素存储了平移变化量deltaZ,deltaY,deltaZ.

    Refs:
    http://mathworld.wolfram.com/Matrix.html
    http://www.gamedev.net/community/forums/topic.asp?topic_id=321862

    展开全文
  • 初等矩阵与初等变换

    千次阅读 2020-12-19 11:01:37
    初等行变换后所得到C,向量中的每个元素分别从左向右乘以矩阵中各行的元素,然后再相加,这个描述稍有点点误解,可以直接以例子来说明,比如说y是3行2,A是3行2,那么初等行变换后C中第二行的结果,...
  • 矩阵问题

    2021-04-25 19:59:15
    二行有n+1个整数,第i个整数表示A[i]. 输出描述 输出第行有个整数,将n个矩阵乘起来所要执行的乘法次数的最小值。 样例输入 4 1 2 3 4 5 样例输出 38 #include<cstdio> #include<algorithm> ...
  • 矩阵乘优化的思考

    2014-04-25 08:08:33
    进行相乘运算,即:arr的第一行乘brr的第一列对应位置之后作和,作为结果的第一一列。arr的第一行乘brr的第二列对应位置之后作和,作为结果的第一二列。。。。一次类推~ 没有做任何优化的代码: __...
  • 两个元素的矩阵乘除法

    万次阅读 2019-01-02 14:11:05
    主要方法就是:用左边矩阵的第一行,逐个乘以右边矩阵的列,第一行与第一列各个元素的乘积相加,第一行与第二列的各个元素的乘积相加。。。。 第二行也是,逐个乘以右边矩阵的列。。。。 第三行。。。 。。。。 ...
  • 输入: 连续相乘矩阵的总个数(不超过20),每个矩阵的维度(因为上矩阵是下矩阵,所以只需输入个n+1维度的数组即可) 输出:最小计算量,以及加括号的方法 源代码: #include using...
  • 算法分析之矩阵问题

    千次阅读 2020-09-19 18:52:42
    矩阵的条件:第矩阵等于第矩阵,此时两个矩阵是可的; 多个矩阵的结果矩阵,其行列等于第矩阵和最后矩阵; 两个矩阵相乘的计算量: 例如: 可知总执行次数为:324=24. ...
  • 摘要因为很久没有写过什么代码,于是打算写矩阵类来练一下手,找找感觉。...(写的比较简陋,凑合着看吧)Matrix类的构成数据成员int row int column long matrix** 动态维数组成员函数Matrix...
  • 这次写的是个简单的矩阵类,这个类里面的包含维数组形式的成员用来存放矩阵,并且可以实现一些矩阵的基本运算,如加法、减法、乘法和赋值等等。(写的比较简陋,凑合着看吧) Matrix类的构成 数据成员 ...
  • 区间DP之矩阵

    2018-03-21 21:06:30
    题目描述:给定n个矩阵,求...=100),以后第二行至n+1行为第i个矩阵的行与输出格式:输出最小相乘次数想法:设f[i][j]为第i个矩阵乘到第j个矩阵的最小相乘次数那么我们可以很简单的得到:f[i][j]=min(f[i][k]+f[k+...
  • 【问题描述】 矩阵是线性代数中的重要概念,应用领域非常广泛,在C/C++中,通常将矩阵定义为维数组。 本问题中,将输入两个矩阵 A 和 B,实现对矩阵... 接下来的一行,为个整数 x, 用于对矩阵 A 进行数
  • 矩阵相乘,左矩阵第一乘以右矩阵一列(分别相乘,第一个数第一个数),完之后相加,即为结果的第一一列的数,依次往下算。 例如:AxB,A为pxq矩阵,B为qxr矩阵,结果矩阵C为pxq。...
  • 动态规划-矩阵详解(java) 问题分析 矩阵问题就是对于给定n个连矩阵,找出种加括号的方法,使得矩阵的...两个矩阵相乘的结果矩阵,其分别等于第矩阵,第矩阵。如果有很...
  • 称为mn矩阵,简称 矩阵,记作 .原理,公式和法则 1.矩阵的加法 (1) 公式 (2) 运算律 2.数乘矩阵 (1) 公式 (2) 运算律 3.矩阵矩阵相乘 (1) 设 , 则 其中 ,且  。 (2)...
  • 索引稀疏矩阵乘法(严蔚敏版) 原理 索引稀疏矩阵查找某一列的元素没那么方便,所以在做矩阵...求Q(2,2)的第一时,肯定是M的第一和N的第一列再累加,然后再M的第一和N的第二列累加 M(2,3)* ...
  • 有时候一个矩阵只包含一或者一列,我们将这种矩阵称之为向量或者列向量。 矩阵相等 两个矩阵维数相等且对应的元素也相等,这两个矩阵相等 矩阵 矩阵可以和标量进行数,规则就是将标量个每一个矩...
  • 列主映射:将矩阵依此从每一列的索引从上至下连续编号,将矩阵的索引映射为一维数组。 本文的多种矩阵均采用主映射,使用一维数组来表达多种矩阵。例如按照常规对矩阵进行描述的C++维数组中,矩阵元素M(3...
  • 输入:首先输入矩阵数量n,接下来n输入矩阵的字母及其第一二维的基数,接下来一行输入需要计算的表达式。 输出:对于每个表达式有个输出,即需要乘法的次数,若乘法无法进行则输出error 样例输入输出
  • 节 常用矩阵运算称为列矩阵(或列向量)。称为矩阵(或向量)。行数相等且列数相等的两个矩阵,称为同型矩阵、矩阵的加法(具体看线性代数)说明:只有当两个矩阵是同型矩阵的时候,才能进行加法运算。、数与...
  • 而初等变化,相当于左乘一个初等矩阵(单位矩阵进行相应的变换)。 那么,问题来了。为什么对其进行变换就相当于左初等阵呢? 我们只是从书上看到这个结论,但并不太清楚为什么会是这样的,接下来的举例...
  • 矩阵加减

    2019-03-31 09:57:52
    教科书告诉你,计算规则是,第一个矩阵第一的每个数字(2和1),各自乘以第矩阵一列对应位置的数字(1和1),然后将乘积相加( 2 x 1 + 1 x 1),得到结果矩阵左上角的那个值3。 也就...
  • 1、矩阵乘法     ... 从定义可以看出:只有当矩阵A的数与矩阵B的行数相等时...个mr矩阵可以乘以个rn矩阵,得到的结果是个mn矩阵,其中的第i第j位置上的数等于前矩阵第i上的
  • 一行是1个整数n(2≤n≤300),表示有n个矩阵,接下来一行有n+1个数,表示是n个矩阵及第n个矩阵,它们之间用空格隔开. Output 输出重叠子问题计算次数和对应的子问题,中间以空格隔开,各子问题的重叠...
  • 输入n个矩阵的维度和一些矩阵的表达式,输出乘法的次数,如果乘法无法进行,输入error 假定A是 m * n 矩阵 B 是 n ...A 矩阵的每一都要和B矩阵的每一列对应相乘 这里的乘法次数是 m * p 又A有n 因此乘法次数...
  • 其他各列是 其后列与倒数第二列的点乘积希尔伯特矩阵是著名的病态矩阵,即任何一个矩阵元素发生较小的变化,整个矩阵的值及逆矩阵都会发生很大变化,病态程度与矩阵阶数呈正相关帕斯卡矩阵的第一和第一列的元素均...
  • /*p是维数组,记录矩阵的规模(第矩阵和其余矩阵); n是矩阵的个;m是维数组,记录计算A[i:j],1所需要的最少数次数m[i][j]; 相对应于m[i][j]的断开位置k记为s[i][j]*/ void MatrixChain(int *p...
  • 1)判断维数组是否为矩阵:如果每数都相等则是矩阵,没有元素的维数组是矩阵 /// /// 判断维数组是否为矩阵 /// /// 维数组 /// <returns>true:是矩阵 false:不是矩阵 private static bool...

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 173
精华内容 69
关键字:

二行二列乘二行一列矩阵