官术网_书友最值得收藏!

Inverse

To find the inverse of a matrix, divide the adjugate of the matrix by its determinant. Since the scalar matrix division is not defined, you will need to multiply the adjugate by the reciprocal of the determinant.

Important note

In this chapter, you will build a matrix multiplication function that uses macros to avoid the need for lower-order matrices. The Chapter03/Sample01 sample in the downloadable materials for this book provides an implementation that utilizes lower-order matrices and is easier to work through with a debugger.

To implement a matrix inverse function, you will first need to be able to find the determinant and adjugate of a 4 x 4 matrix. Both functions rely on being able to find the minor of an element in the matrix:

  1. Create a new macro in mat4.cpp. This macro will find the minor of one element in the matrix, given an array of floats, and three rows and three columns to cut from the matrix:

    #define M4_3X3MINOR(x, c0, c1, c2, r0, r1, r2) \

       (x[c0*4+r0]*(x[c1*4+r1]*x[c2*4+r2]-x[c1*4+r2]* \

       x[c2*4+r1])-x[c1*4+r0]*(x[c0*4+r1]*x[c2*4+r2]- \

       x[c0*4+r2]*x[c2*4+r1])+x[c2*4+r0]*(x[c0*4+r1]* \

       x[c1*4+r2]-x[c0*4+r2]*x[c1*4+r1]))

  2. With the M4_3X3MINOR macro defined, implement the determinant function in mat4.cpp. Since the determinant will multiply each element by the cofactor, some of the values need to be negated. Don't forget to add the function declaration to mat4.h:

    float determinant(const mat4& m) {

       return  m.v[0] *M4_3X3MINOR(m.v, 1, 2, 3, 1, 2, 3)  

             - m.v[4] *M4_3X3MINOR(m.v, 0, 2, 3, 1, 2, 3)  

             + m.v[8] *M4_3X3MINOR(m.v, 0, 1, 3, 1, 2, 3)  

             - m.v[12]*M4_3X3MINOR(m.v, 0, 1, 2, 1, 2, 3);

    }

  3. Next, implement the adjugate function in mat4.cpp. Don't forget to add the function declaration to mat4.h. Use the M4_3X3MINOR macro to find the matrix of minors, then negate the appropriate elements to create the cofactor matrix. Finally, return the transpose of the cofactor matrix:

    mat4 adjugate(const mat4& m) {

       //Cof (M[i, j]) = Minor(M[i, j]] * pow(-1, i + j)

       mat4 cofactor;

       cofactor.v[0] = M4_3X3MINOR(m.v, 1, 2, 3, 1, 2, 3);

       cofactor.v[1] =-M4_3X3MINOR(m.v, 1, 2, 3, 0, 2, 3);

       cofactor.v[2] = M4_3X3MINOR(m.v, 1, 2, 3, 0, 1, 3);

       cofactor.v[3] =-M4_3X3MINOR(m.v, 1, 2, 3, 0, 1, 2);

       cofactor.v[4] =-M4_3X3MINOR(m.v, 0, 2, 3, 1, 2, 3);

       cofactor.v[5] = M4_3X3MINOR(m.v, 0, 2, 3, 0, 2, 3);

       cofactor.v[6] =-M4_3X3MINOR(m.v, 0, 2, 3, 0, 1, 3);

       cofactor.v[7] = M4_3X3MINOR(m.v, 0, 2, 3, 0, 1, 2);

       cofactor.v[8] = M4_3X3MINOR(m.v, 0, 1, 3, 1, 2, 3);

       cofactor.v[9] =-M4_3X3MINOR(m.v, 0, 1, 3, 0, 2, 3);

       cofactor.v[10]= M4_3X3MINOR(m.v, 0, 1, 3, 0, 1, 3);

       cofactor.v[11]=-M4_3X3MINOR(m.v, 0, 1, 3, 0, 1, 2);

       cofactor.v[12]=-M4_3X3MINOR(m.v, 0, 1, 2, 1, 2, 3);

       cofactor.v[13]= M4_3X3MINOR(m.v, 0, 1, 2, 0, 2, 3);

       cofactor.v[14]=-M4_3X3MINOR(m.v, 0, 1, 2, 0, 1, 3);

       cofactor.v[15]= M4_3X3MINOR(m.v, 0, 1, 2, 0, 1, 2);

       return transposed(cofactor);

    }

  4. Now that the determinant and adjugate functions are finished, the implementation of the inverse function for a 4 x 4 matrix should be straightforward. Implement the inverse function in mat4.cpp. Don't forget to add the function declaration to mat4.h:

    mat4 inverse(const mat4& m) {

        float det = determinant(m);

            

        if (det == 0.0f) {

            cout << " Matrix determinant is 0\n";

            return mat4();

        }

        mat4 adj = adjugate(m);

        return adj * (1.0f / det);

    }

  5. The inverse function takes a constant matrix reference and returns a new matrix that is the inverse of the provided matrix. Implement an invert convenience function in mat4.cpp. This convenience function will invert the matrix inline, modifying the argument. Don't forget to add the function declaration to mat4.h:

    void invert(mat4& m) {

        float det = determinant(m);

        if (det == 0.0f) {

            std::cout << "Matrix determinant is 0\n";

            m = mat4();

            return;

        }

        m = adjugate(m) * (1.0f / det);

    }

Inverting matrices is a relatively expensive function. Matrices that only encode the position and rotation can be inverted faster because the inverse of a 3 x 3 rotation matrix is the same as its transpose.

You will learn how to implement this fast inverse in the next section when implementing the lookAt function.

主站蜘蛛池模板: 大石桥市| 深州市| 吴川市| 吉木萨尔县| 新密市| 仙游县| 磐安县| 林甸县| 武乡县| 仁怀市| 获嘉县| 上栗县| 天津市| 安龙县| 青岛市| 鄂州市| 台南市| 湟中县| 石景山区| 西昌市| 姜堰市| 保德县| 绩溪县| 竹北市| 霍林郭勒市| 香港 | 靖江市| 吕梁市| 垦利县| 福海县| 东丽区| 基隆市| 朔州市| 奎屯市| 江城| 崇礼县| 新巴尔虎左旗| 山丹县| 梓潼县| 萨嘎县| 武胜县|