4x4矩阵求逆

最近学习自定义光栅化渲染器,在学习矩阵变换的时候,求矩阵的逆矩阵的时候遇到的一些问题,特记录在此。

typedef struct MATRIX3X3_TYPE // 3×3矩阵
    {
        union
        {
            double M[3][3];
            struct
            {
                double M00, M01, M02;
                double M10, M11, M12;
                double M20, M21, M22;
            };
        };
    } MATRIX3X3, *MATRIX3X3_PTR;

    typedef struct MATRIX4X4_TYPE //4×4矩阵
    {
        union
        {
            double M[4][4];
            struct
            {
                double M00, M01, M02, M03;
                double M10, M11, M12, M13;
                double M20, M21, M22, M23;
                double M30, M31, M32, M33;
            };
        };
    } MATRIX4X4, *MATRIX4X4_PTR;

// 求 3x3 矩阵的逆矩阵
int _CPPYIN_Math::MatrixInverse(MATRIX3X3_PTR m, MATRIX3X3_PTR mi)
{
    double det = m->M00*(m->M11*m->M22 - m->M21*m->M12) - 
            m->M01*(m->M10*m->M22 - m->M20*m->M12) + 
            m->M02*(m->M10*m->M21 - m->M20*m->M11);

    if (abs(det) < EPSILON)
        return 0;

    double det_inv = 1.0/det;

    mi->M00 =  det_inv*(m->M11*m->M22 - m->M21*m->M12);
    mi->M10 = -det_inv*(m->M10*m->M22 - m->M20*m->M12);
    mi->M20 =  det_inv*(m->M10*m->M21 - m->M20*m->M11);

    mi->M01 = -det_inv*(m->M01*m->M22 - m->M21*m->M02);
    mi->M11 =  det_inv*(m->M00*m->M22 - m->M20*m->M02);
    mi->M21 = -det_inv*(m->M00*m->M21 - m->M20*m->M01);

    mi->M02 =  det_inv*(m->M01*m->M12 - m->M11*m->M02);
    mi->M12 = -det_inv*(m->M00*m->M12 - m->M10*m->M02);
    mi->M22 =  det_inv*(m->M00*m->M11 - m->M10*m->M01);

    return 1;
}

// 求4x4 矩阵的逆矩阵
// m 源矩阵   mi 源矩阵的逆矩阵
int _CPPYIN_Math::MatrixInverse(MATRIX4X4_PTR m, MATRIX4X4_PTR mi)
{
    // 矩阵的行列式
    double det =  ( m->M00 * ( m->M11 * m->M22 - m->M12 * m->M21 ) -
                   m->M01 * ( m->M10 * m->M22 - m->M12 * m->M20 ) +
                   m->M02 * ( m->M10 * m->M21 - m->M11 * m->M20 ) );

    // 先判断行列式是否为0if (abs(det) < EPSILON)
       return 0;

    double det_inv  = 1.0 / det;

    mi->M00 =  det_inv * ( m->M11 * m->M22 - m->M12 * m->M21 );
    mi->M01 = -det_inv * ( m->M01 * m->M22 - m->M02 * m->M21 );
    mi->M02 =  det_inv * ( m->M01 * m->M12 - m->M02 * m->M11 );
    mi->M03 = 0.0;

    mi->M10 = -det_inv * ( m->M10 * m->M22 - m->M12 * m->M20 );
    mi->M11 =  det_inv * ( m->M00 * m->M22 - m->M02 * m->M20 );
    mi->M12 = -det_inv * ( m->M00 * m->M12 - m->M02 * m->M10 );
    mi->M13 = 0.0;

    mi->M20 =  det_inv * ( m->M10 * m->M21 - m->M11 * m->M20 );
    mi->M21 = -det_inv * ( m->M00 * m->M21 - m->M01 * m->M20 );
    mi->M22 =  det_inv * ( m->M00 * m->M11 - m->M01 * m->M10 );
    mi->M23 = 0.0;

    mi->M30 = -( m->M30 * mi->M00 + m->M31 * mi->M10 + m->M32 * mi->M20 );
    mi->M31 = -( m->M30 * mi->M01 + m->M31 * mi->M11 + m->M32 * mi->M21 );
    mi->M32 = -( m->M30 * mi->M02 + m->M31 * mi->M12 + m->M32 * mi->M22 );
    mi->M33 = 1.0;

    return 1;
}

如上,是求3x3矩阵和4x4矩阵的逆矩阵,大家都知道矩阵的逆 A-1 = A*/|A|,不知道的可以去看下线代课本。

前面3*3矩阵求法是一般的求法,先求矩阵的行列式|A|,如果不等于0的话,则有逆矩阵。接着求A*(伴随矩阵),这个求法是先求A的代数余子式,再转置即可。

但是在求4x4矩阵的时候,前3行3列求解步骤和上面求3x3的逆是一样的,第四列,我们赋值0,0,0,1。因为在我们这个渲染器中顶点是以行向量的形式存在的,所以,第四列直接赋值,0,0,0,1,第四行才代表的是平移矩阵。如果是列向量的话,则正好相反,第四列代表平移矩阵,第四行赋值0,0,0,1。

言归正传,第四行的前3个参数的求法是不是有点诡异。是的,我们要说的就是这3个数是怎么求出来的。

这里写图片描述

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 矩阵的逆矩阵是指对于给定的n方阵A,存在一个n方阵B,满足AB=BA=I,其中I为单位矩阵。 在Qt中,我们可以使用QGenericMatrix类来实现矩阵的逆操作。首先,我们需要定义一个QGenericMatrix对象,用于存储原始矩阵A。接下来,我们可以使用QGenericMatrix的inverse()函数来计算矩阵的逆矩阵B。最后,我们可以通过访问B的元素来获取逆矩阵的值。 下面是一个使用Qt实现矩阵求逆矩阵的示例代码: ```cpp #include <QtMath> #include <QGenericMatrix> // 定义一个4x4的原始矩阵A QGenericMatrix<4, 4, qreal> matrixA; // 填充原始矩阵A的元素 matrixA.setRow(0, QVector4D(1, 2, 3, 4)); matrixA.setRow(1, QVector4D(5, 6, 7, 8)); matrixA.setRow(2, QVector4D(9, 1, 2, 3)); matrixA.setRow(3, QVector4D(4, 5, 6, 7)); // 计算逆矩阵B QGenericMatrix<4, 4, qreal> matrixB = matrixA.inverted(); // 输出逆矩阵B的值 for (int i = 0; i < 4; i++) { qreal* row = matrixB[i]; for (int j = 0; j < 4; j++) { qreal value = row[j]; qDebug() << value; } } ``` 以上代码在Qt中实现了一个4x4矩阵求逆矩阵的示例。首先,我们定义了一个4x4的QGenericMatrix对象matrixA,并使用setRow()函数填充了原始矩阵A的元素。然后,我们使用inverted()函数计算了逆矩阵B,并将结果存储在了另一个QGenericMatrix对象matrixB中。最后,我们通过访问matrixB的元素来获取逆矩阵的值,并使用QDebug输出了结果。 需要注意的是,上述示例代码中的矩阵元素类型为qreal,可以根据需要进行修改。另外,Qt还提供了其他方便的矩阵操作函数和类,可以根据实际需要进行选择和使用。 ### 回答2: 在数学中,矩阵的逆矩阵(Inverse Matrix)是指满足乘法运算下的单位元的矩阵。解矩阵的逆矩阵在很多应用中非常重要,因为它可以用来解线性方程组、计算向量的逆向变换等。 Qt是一个流行的C++开发框架,它提供了丰富的矩阵操作类和函数,可以简化矩阵运算的实现。下面是一个使用Qt实现矩阵求逆矩阵的示例代码: ```cpp #include <QMatrix4x4> #include <QDebug> int main() { QMatrix4x4 matrix; matrix(0, 0) = 1; matrix(0, 1) = 2; matrix(0, 2) = 3; matrix(0, 3) = 4; matrix(1, 0) = 5; matrix(1, 1) = 6; matrix(1, 2) = 7; matrix(1, 3) = 8; matrix(2, 0) = 9; matrix(2, 1) = 10; matrix(2, 2) = 11; matrix(2, 3) = 12; matrix(3, 0) = 13; matrix(3, 1) = 14; matrix(3, 2) = 15; matrix(3, 3) = 16; if (matrix.determinant() != 0) { // 解矩阵的逆矩阵 QMatrix4x4 inverseMatrix = matrix.inverted(); // 输出逆矩阵的元素 for (int row = 0; row < 4; ++row) { for (int column = 0; column < 4; ++column) { qDebug() << inverseMatrix(row, column); } } } else { qDebug() << "矩阵不可逆!"; } return 0; } ``` 以上代码通过QMatrix4x4类创建了一个4x4矩阵,并对其进行赋值。然后使用inverted()函数解矩阵的逆矩阵,并通过循环输出逆矩阵的元素。需要注意的是,在逆矩阵之前,先判断矩阵的行列式是否为0,如果为0则表示矩阵不可逆。 以上就是使用Qt实现矩阵求逆矩阵的简单示例。通过Qt这个强大的框架,我们可以轻松地进行矩阵运算,提高开发效率。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值