行向量,列向量,行主序矩阵,列主序矩阵(row vector,column vector,row major-matrix,column-major matrix)...

关于这个话题,网上有n多个版本,今天,我也来说说这个话题。
(一)首先,无论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;
   

转载于:https://www.cnblogs.com/cgwolver/archive/2009/07/29/1533570.html

在MATLAB中,可以使用列主序消元法(Gaussian elimination with column pivoting)来求解线性方程组。列主序消元法是一种常用的数值方法,用于解决具有大量未知数和方程的线性方程组。 下面是MATLAB中使用列主序消元法求解线性方程组的步骤: 1. 构建增广矩阵:将线性方程组的系数矩阵和常数向量合并成一个增广矩阵。 2. 主元素选取:选择增广矩阵中当前的主元素,即绝对值最大的元素所在的行。 3. 主元素交换:将选取的主元素所在行与当前的第一行进行交换,确保主元素在当前的第一行。 4. 消元操作:使用当前的第一行元素将下面的行进行消元,使得当前下面的元素都变为0。 5. 重复步骤2-4:对于每一,重复进行主元素选取、主元素交换和消元操作,直到所有都处理完毕。 6. 回代求解:从最后一行开始,利用已经得到的上三角矩阵,通过回代求解出未知数的值。 下面是一个MATLAB代码示例,演示了如何使用列主序消元法求解线性方程组: ```matlab function x = gaussianElimination(A, b) n = size(A, 1); Ab = [A, b]; % 构建增广矩阵 for k = 1:n-1 [~, pivot] = max(abs(Ab(k:n, k))); % 选取主元素 pivot = pivot + k - 1; Ab([k, pivot], :) = Ab([pivot, k], :); % 主元素交换 for i = k+1:n factor = Ab(i, k) / Ab(k, k); Ab(i, k:n+1) = Ab(i, k:n+1) - factor * Ab(k, k:n+1); % 消元操作 end end x = zeros(n, 1); x(n) = Ab(n, n+1) / Ab(n, n); for i = n-1:-1:1 x(i) = (Ab(i, n+1) - Ab(i, i+1:n) * x(i+1:n)) / Ab(i, i); % 回代求解 end end ``` 使用上述函数,可以通过传入系数矩阵A和常数向量b来求解线性方程组。例如,假设有以下线性方程组: ``` 2x + 3y - z = 7 3x + 2y + 2z = 12 x - y + z = 3 ``` 可以使用以下代码进行求解: ```matlab A = [2, 3, -1; 3, 2, 2; 1, -1, 1]; b = [7; 12; 3]; x = gaussianElimination(A, b); disp(x); ``` 输出结果为: ``` x = 2 1 3 ``` 这样就得到了线性方程组的解x。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值