zoukankan      html  css  js  c++  java
  • 矩阵及变换,以及矩阵在DirectX和OpenGL中的运用问题:左乘 or 右乘,存储问题:行优先 or 列优先,

    1. 矢量和矩阵的乘法的线性代数表示

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

    2. “矩阵的存储方式”

      矩阵存储方式有两种,一种是“行主序(row-major order)/行优先”,另一种就是“列主序(column-major order)/列优先”/

    2.1 Direct3D 采用行主序(Row major)存储

    “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.”

    2.2 OpenGL 采用列主序(Colume major)存储

    “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”

      存储顺序说明了线性代数中的矩阵如何在线性的内存数组中存储,d3d 将每一行在数组中按行存储,而opengl将每一列存储到数组的每一行中:

      因此,对于线程代数中的同一个矩阵,则在d3d和OpenGL中有不同的表示形式:

                      线代矩阵:a11,a12,a13,a14            d3d保存:  a11,a12,a13,a14            OpenGL保存: 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

    3. 矩阵乘法顺序和规则

           矩阵乘法在线性代数中的定义是确定的,然而在不同的实现中出现了“左乘”和“右乘”的区别,或者叫做“前乘(pre-multiply),后乘(post-multiply)” 。

      这个规则取决于vector的表示形式,即行向量还是列向量。

      如果是行向量,其实就是一个行矩阵。那么表示线性代数意义的“行x列”,就是前乘。矩阵乘法也是如此。

    3.1 Direct3d
        D3D 是行向量,行优先存储,OpenGL是列向量,列优先存储。同一个矩阵用D3D存储还是用opengl存储虽然不同,但是变换的结果却是相同的。 

         (1)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中的向量是采用Col-major保存的,即将向量需要保存为列向量形式。从而在执行向量和矩阵的乘法的时候,需要将“列”保存的【向量】,还原为“行”向量,然后采用“标准向量与矩阵相乘”的标准规则进行进行计算即可。

      (2)再来看一下opengl 矩阵相乘,“用a的每一列去乘b的每一行”。

        A*B = B‘ *A’= C

        由于在OpenGL中A和B都是列为主的矩阵,B’ * A‘ 的效果,就是用B的列 向量 X A的行向量,从而就是运算后的矩阵中的每一个列的值。

             从下列代码中可以看出,计算的结果还是以Col-Major保存的矩阵。且C的每个列向量中的每个元素即为:B的列向量与A的行向量 逐个乘机的和。

    /*
    ** 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;
      }
    }

     

      因为opengl 变换向量是把向量视作列向量,并同矩阵的每一列相乘,用来实现线性代数中同一个变换。

          

    endl;

  • 相关阅读:
    475. Heaters
    69. Sqrt(x)
    83. Remove Duplicates from Sorted List Java solutions
    206. Reverse Linked List java solutions
    100. Same Tree Java Solutions
    1. Two Sum Java Solutions
    9. Palindrome Number Java Solutions
    112. Path Sum Java Solutin
    190. Reverse Bits Java Solutin
    202. Happy Number Java Solutin
  • 原文地址:https://www.cnblogs.com/icmzn/p/13531265.html
Copyright © 2011-2022 走看看