「逆行列」の版間の差分

提供: MonoBook
ナビゲーションに移動 検索に移動
 
(同じ利用者による、間の1版が非表示)
4行目: 4行目:
  
 
たとえば[[バーテックスシェーダー]]で[[ローカル座標系]]から[[ワールド座標系]]に変換してしまった頂点位置を[[ピクセルシェーダー]]で[[ローカル座標系]]に戻したい場合などに使われる。
 
たとえば[[バーテックスシェーダー]]で[[ローカル座標系]]から[[ワールド座標系]]に変換してしまった頂点位置を[[ピクセルシェーダー]]で[[ローカル座標系]]に戻したい場合などに使われる。
 +
 +
== 3x3行列の場合 ==
 +
:<math>
 +
A^{-1} = \frac{1}{\text{det}(A)} \begin{bmatrix}
 +
(a_{11}a_{22} - a_{12}a_{21}) & (a_{02}a_{21} - a_{01}a_{22}) & (a_{01}a_{12} - a_{02}a_{11}) \\
 +
(a_{12}a_{20} - a_{10}a_{22}) & (a_{00}a_{22} - a_{02}a_{20}) & (a_{02}a_{10} - a_{00}a_{12}) \\
 +
(a_{10}a_{21} - a_{11}a_{20}) & (a_{01}a_{20} - a_{00}a_{21}) & (a_{00}a_{11} - a_{01}a_{10})
 +
\end{bmatrix}
 +
</math>
 +
 +
C言語風に実装すると以下のような感じ。
 +
<source lang="c">
 +
bool inverseMatrix(float a[3][3], float inv[3][3]) {
 +
    float det = a[0][0] * (a[1][1] * a[2][2] - a[2][1] * a[1][2])
 +
              - a[0][1] * (a[1][0] * a[2][2] - a[1][2] * a[2][0])
 +
              + a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0]);
 +
 +
    if (det == 0) {
 +
        printf("The matrix is singular and cannot be inverted.\n");
 +
        return false;
 +
    }
 +
 +
    float invdet = 1 / det;
 +
 +
    inv[0][0] =  (a[1][1] * a[2][2] - a[2][1] * a[1][2]) * invdet;
 +
    inv[0][1] = -(a[0][1] * a[2][2] - a[0][2] * a[2][1]) * invdet;
 +
    inv[0][2] =  (a[0][1] * a[1][2] - a[0][2] * a[1][1]) * invdet;
 +
 +
    inv[1][0] = -(a[1][0] * a[2][2] - a[1][2] * a[2][0]) * invdet;
 +
    inv[1][1] =  (a[0][0] * a[2][2] - a[0][2] * a[2][0]) * invdet;
 +
    inv[1][2] = -(a[0][0] * a[1][2] - a[1][0] * a[0][2]) * invdet;
 +
 +
    inv[2][0] =  (a[1][0] * a[2][1] - a[2][0] * a[1][1]) * invdet;
 +
    inv[2][1] = -(a[0][0] * a[2][1] - a[2][0] * a[0][1]) * invdet;
 +
    inv[2][2] =  (a[0][0] * a[1][1] - a[1][0] * a[0][1]) * invdet;
 +
 +
    return true;
 +
}
 +
</source>
 +
 +
== 4x4行列の場合 ==
 +
 +
C言語風に実装すると以下のような感じ。
 +
<source lang="c">
 +
bool inverseMatrix(float a[4][4], float inv[4][4]) {
 +
    float det = a[0][0] * (a[1][1] * (a[2][2] * a[3][3] - a[3][2] * a[2][3]) - a[2][1] * (a[1][2] * a[3][3] - a[3][2] * a[1][3]) + a[3][1] * (a[1][2] * a[2][3] - a[2][2] * a[1][3]))
 +
              - a[0][1] * (a[1][0] * (a[2][2] * a[3][3] - a[3][2] * a[2][3]) - a[2][0] * (a[1][2] * a[3][3] - a[3][2] * a[1][3]) + a[3][0] * (a[1][2] * a[2][3] - a[2][2] * a[1][3]))
 +
              + a[0][2] * (a[1][0] * (a[2][1] * a[3][3] - a[3][1] * a[2][3]) - a[2][0] * (a[1][1] * a[3][3] - a[3][1] * a[1][3]) + a[3][0] * (a[1][1] * a[2][3] - a[2][1] * a[1][3]))
 +
              - a[0][3] * (a[1][0] * (a[2][1] * a[3][2] - a[3][1] * a[2][2]) - a[2][0] * (a[1][1] * a[3][2] - a[3][1] * a[1][2]) + a[3][0] * (a[1][1] * a[2][2] - a[2][1] * a[1][2]));
 +
 +
    if (det == 0) {
 +
        printf("The matrix is singular and cannot be inverted.\n");
 +
        return false;
 +
    }
 +
 +
    float invdet = 1 / det;
 +
 +
    inv[0][0] =  ((a[1][1] * (a[2][2] * a[3][3] - a[3][2] * a[2][3]) - a[2][1] * (a[1][2] * a[3][3] - a[3][2] * a[1][3]) + a[3][1] * (a[1][2] * a[2][3] - a[2][2] * a[1][3])) * invdet;
 +
    inv[0][1] = -((a[1][0] * (a[2][2] * a[3][3] - a[3][2] * a[2][3]) - a[2][0] * (a[1][2] * a[3][3] - a[3][2] * a[1][3]) + a[3][0] * (a[1][2] * a[2][3] - a[2][2] * a[1][3])) * invdet);
 +
    inv[0][2] =  ((a[1][0] * (a[2][1] * a[3][3] - a[3][1] * a[2][3]) - a[2][0] * (a[1][1] * a[3][3] - a[3][1] * a[1][3]) + a[3][0] * (a[1][1] * a[2][3] - a[2][1] * a[1][3])) * invdet;
 +
    inv[0][3] = -((a[1][0] * (a[2][1] * a[3][2] - a[3][1] * a[2][2]) - a[2][0] * (a[1][1] * a[3][2] - a[3][1] * a[1][2]) + a[3][0] * (a[1][1] * a[2][2] - a[2][1] * a[1][2])) * invdet);
 +
 +
    inv[1][0] = -((a[0][1] * (a[2][2] * a[3][3] - a[3][2] * a[2][3]) - a[2][1] * (a[0][2] * a[3][3] - a[3][2] * a[0][3]) + a[3][1] * (a[0][2] * a[2][3] - a[2][2] * a[0][3])) * invdet);
 +
    inv[1][1] =  ((a[0][0] * (a[2][2] * a[3][3] - a[3][2] * a[2][3]) - a[2][0] * (a[0][2] * a[3][3] - a[3][2] * a[0][3]) + a[3][0] * (a[0][2] * a[2][3] - a[2][2] * a[0][3])) * invdet);
 +
    inv[1][2] = -((a[0][0] * (a[2][1] * a[3][3] - a[3][1] * a[2][3]) - a[2][0] * (a[0][1] * a[3][3] - a[3][1] * a[0][3]) + a[3][0] * (a[0][1] * a[2][3] - a[2][1] * a[0][3])) * invdet);
 +
    inv[1][3] =  ((a[0][0] * (a[2][1] * a[3][2] - a[3][1] * a[2][2]) - a[2][0] * (a[0][1] * a[3][2] - a[3][1] * a[0][2]) + a[3][0] * (a[0][1] * a[2][2] - a[2][1] * a[0][2])) * invdet);
 +
 +
    inv[2][0] =  ((a[0][1] * (a[1][2] * a[3][3] - a[3][2] * a[1][3]) - a[1][1] * (a[0][2] * a[3][3] - a[3][2] * a[0][3]) + a[3][1] * (a[0][2] * a[1][3] - a[1][2] * a[0][3])) * invdet);
 +
    inv[2][1] = -((a[0][0] * (a[1][2] * a[3][3] - a[3][2] * a[1][3]) - a[1][0] * (a[0][2] * a[3][3] - a[3][2] * a[0][3]) + a[3][0] * (a[0][2] * a[1][3] - a[1][2] * a[0][3])) * invdet);
 +
    inv[2][2] =  ((a[0][0] * (a[1][1] * a[3][3] - a[3][1] * a[1][3]) - a[1][0] * (a[0][1] * a[3][3] - a[3][1] * a[0][3]) + a[3][0] * (a[0][1] * a[1][3] - a[1][1] * a[0][3])) * invdet);
 +
    inv[2][3] = -((a[0][0] * (a[1][1] * a[3][2] - a[3][1] * a[1][2]) - a[1][0] * (a[0][1] * a[3][2] - a[3][1] * a[0][2]) + a[3][0] * (a[0][1] * a[1][2] - a[1][1] * a[0][2])) * invdet);
 +
 +
    inv[3][0] = -((a[0][1] * (a[1][2] * a[2][3] - a[2][2] * a[1][3]) - a[1][1] * (a[0][2] * a[2][3] - a[2][2] * a[0][3]) + a[2][1] * (a[0][2] * a[1][3] - a[1][2] * a[0][3])) * invdet);
 +
    inv[3][1] =  ((a[0][0] * (a[1][2] * a[2][3] - a[2][2] * a[1][3]) - a[1][0] * (a[0][2] * a[2][3] - a[2][2] * a[0][3]) + a[2][0] * (a[0][2] * a[1][3] - a[1][2] * a[0][3])) * invdet);
 +
    inv[3][2] = -((a[0][0] * (a[1][1] * a[2][3] - a[2][1] * a[1][3]) - a[1][0] * (a[0][1] * a[2][3] - a[2][1] * a[0][3]) + a[2][0] * (a[0][1] * a[1][3] - a[1][1] * a[0][3])) * invdet);
 +
    inv[3][3] =  ((a[0][0] * (a[1][1] * a[2][2] - a[2][1] * a[1][2]) - a[1][0] * (a[0][1] * a[2][2] - a[2][1] * a[0][2]) + a[2][0] * (a[0][1] * a[1][2] - a[1][1] * a[0][2])) * invdet);
 +
 +
    return true;
 +
}
 +
</source>
  
 
== 関連項目 ==
 
== 関連項目 ==
 
 
* [[行列]]
 
* [[行列]]
 
* [[逆行列]]
 
* [[逆行列]]
 
* [[転置行列]]
 
* [[転置行列]]

2023年12月22日 (金) 05:10時点における最新版

逆行列(inverse matrix)とは、行列逆数のようなもの。

主に3DCGの世界では頂点の座標系を「戻す」のによく使われる。

たとえばバーテックスシェーダーローカル座標系からワールド座標系に変換してしまった頂点位置をピクセルシェーダーローカル座標系に戻したい場合などに使われる。

3x3行列の場合[編集 | ソースを編集]

C言語風に実装すると以下のような感じ。

bool inverseMatrix(float a[3][3], float inv[3][3]) {
    float det = a[0][0] * (a[1][1] * a[2][2] - a[2][1] * a[1][2]) 
              - a[0][1] * (a[1][0] * a[2][2] - a[1][2] * a[2][0]) 
              + a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0]);

    if (det == 0) {
        printf("The matrix is singular and cannot be inverted.\n");
        return false;
    }

    float invdet = 1 / det;

    inv[0][0] =  (a[1][1] * a[2][2] - a[2][1] * a[1][2]) * invdet;
    inv[0][1] = -(a[0][1] * a[2][2] - a[0][2] * a[2][1]) * invdet;
    inv[0][2] =  (a[0][1] * a[1][2] - a[0][2] * a[1][1]) * invdet;

    inv[1][0] = -(a[1][0] * a[2][2] - a[1][2] * a[2][0]) * invdet;
    inv[1][1] =  (a[0][0] * a[2][2] - a[0][2] * a[2][0]) * invdet;
    inv[1][2] = -(a[0][0] * a[1][2] - a[1][0] * a[0][2]) * invdet;

    inv[2][0] =  (a[1][0] * a[2][1] - a[2][0] * a[1][1]) * invdet;
    inv[2][1] = -(a[0][0] * a[2][1] - a[2][0] * a[0][1]) * invdet;
    inv[2][2] =  (a[0][0] * a[1][1] - a[1][0] * a[0][1]) * invdet;

    return true;
}

4x4行列の場合[編集 | ソースを編集]

C言語風に実装すると以下のような感じ。

bool inverseMatrix(float a[4][4], float inv[4][4]) {
    float det = a[0][0] * (a[1][1] * (a[2][2] * a[3][3] - a[3][2] * a[2][3]) - a[2][1] * (a[1][2] * a[3][3] - a[3][2] * a[1][3]) + a[3][1] * (a[1][2] * a[2][3] - a[2][2] * a[1][3]))
              - a[0][1] * (a[1][0] * (a[2][2] * a[3][3] - a[3][2] * a[2][3]) - a[2][0] * (a[1][2] * a[3][3] - a[3][2] * a[1][3]) + a[3][0] * (a[1][2] * a[2][3] - a[2][2] * a[1][3]))
              + a[0][2] * (a[1][0] * (a[2][1] * a[3][3] - a[3][1] * a[2][3]) - a[2][0] * (a[1][1] * a[3][3] - a[3][1] * a[1][3]) + a[3][0] * (a[1][1] * a[2][3] - a[2][1] * a[1][3]))
              - a[0][3] * (a[1][0] * (a[2][1] * a[3][2] - a[3][1] * a[2][2]) - a[2][0] * (a[1][1] * a[3][2] - a[3][1] * a[1][2]) + a[3][0] * (a[1][1] * a[2][2] - a[2][1] * a[1][2]));

    if (det == 0) {
        printf("The matrix is singular and cannot be inverted.\n");
        return false;
    }

    float invdet = 1 / det;

    inv[0][0] =  ((a[1][1] * (a[2][2] * a[3][3] - a[3][2] * a[2][3]) - a[2][1] * (a[1][2] * a[3][3] - a[3][2] * a[1][3]) + a[3][1] * (a[1][2] * a[2][3] - a[2][2] * a[1][3])) * invdet;
    inv[0][1] = -((a[1][0] * (a[2][2] * a[3][3] - a[3][2] * a[2][3]) - a[2][0] * (a[1][2] * a[3][3] - a[3][2] * a[1][3]) + a[3][0] * (a[1][2] * a[2][3] - a[2][2] * a[1][3])) * invdet);
    inv[0][2] =  ((a[1][0] * (a[2][1] * a[3][3] - a[3][1] * a[2][3]) - a[2][0] * (a[1][1] * a[3][3] - a[3][1] * a[1][3]) + a[3][0] * (a[1][1] * a[2][3] - a[2][1] * a[1][3])) * invdet;
    inv[0][3] = -((a[1][0] * (a[2][1] * a[3][2] - a[3][1] * a[2][2]) - a[2][0] * (a[1][1] * a[3][2] - a[3][1] * a[1][2]) + a[3][0] * (a[1][1] * a[2][2] - a[2][1] * a[1][2])) * invdet);

    inv[1][0] = -((a[0][1] * (a[2][2] * a[3][3] - a[3][2] * a[2][3]) - a[2][1] * (a[0][2] * a[3][3] - a[3][2] * a[0][3]) + a[3][1] * (a[0][2] * a[2][3] - a[2][2] * a[0][3])) * invdet);
    inv[1][1] =  ((a[0][0] * (a[2][2] * a[3][3] - a[3][2] * a[2][3]) - a[2][0] * (a[0][2] * a[3][3] - a[3][2] * a[0][3]) + a[3][0] * (a[0][2] * a[2][3] - a[2][2] * a[0][3])) * invdet);
    inv[1][2] = -((a[0][0] * (a[2][1] * a[3][3] - a[3][1] * a[2][3]) - a[2][0] * (a[0][1] * a[3][3] - a[3][1] * a[0][3]) + a[3][0] * (a[0][1] * a[2][3] - a[2][1] * a[0][3])) * invdet);
    inv[1][3] =  ((a[0][0] * (a[2][1] * a[3][2] - a[3][1] * a[2][2]) - a[2][0] * (a[0][1] * a[3][2] - a[3][1] * a[0][2]) + a[3][0] * (a[0][1] * a[2][2] - a[2][1] * a[0][2])) * invdet);

    inv[2][0] =  ((a[0][1] * (a[1][2] * a[3][3] - a[3][2] * a[1][3]) - a[1][1] * (a[0][2] * a[3][3] - a[3][2] * a[0][3]) + a[3][1] * (a[0][2] * a[1][3] - a[1][2] * a[0][3])) * invdet);
    inv[2][1] = -((a[0][0] * (a[1][2] * a[3][3] - a[3][2] * a[1][3]) - a[1][0] * (a[0][2] * a[3][3] - a[3][2] * a[0][3]) + a[3][0] * (a[0][2] * a[1][3] - a[1][2] * a[0][3])) * invdet);
    inv[2][2] =  ((a[0][0] * (a[1][1] * a[3][3] - a[3][1] * a[1][3]) - a[1][0] * (a[0][1] * a[3][3] - a[3][1] * a[0][3]) + a[3][0] * (a[0][1] * a[1][3] - a[1][1] * a[0][3])) * invdet);
    inv[2][3] = -((a[0][0] * (a[1][1] * a[3][2] - a[3][1] * a[1][2]) - a[1][0] * (a[0][1] * a[3][2] - a[3][1] * a[0][2]) + a[3][0] * (a[0][1] * a[1][2] - a[1][1] * a[0][2])) * invdet);

    inv[3][0] = -((a[0][1] * (a[1][2] * a[2][3] - a[2][2] * a[1][3]) - a[1][1] * (a[0][2] * a[2][3] - a[2][2] * a[0][3]) + a[2][1] * (a[0][2] * a[1][3] - a[1][2] * a[0][3])) * invdet);
    inv[3][1] =  ((a[0][0] * (a[1][2] * a[2][3] - a[2][2] * a[1][3]) - a[1][0] * (a[0][2] * a[2][3] - a[2][2] * a[0][3]) + a[2][0] * (a[0][2] * a[1][3] - a[1][2] * a[0][3])) * invdet);
    inv[3][2] = -((a[0][0] * (a[1][1] * a[2][3] - a[2][1] * a[1][3]) - a[1][0] * (a[0][1] * a[2][3] - a[2][1] * a[0][3]) + a[2][0] * (a[0][1] * a[1][3] - a[1][1] * a[0][3])) * invdet);
    inv[3][3] =  ((a[0][0] * (a[1][1] * a[2][2] - a[2][1] * a[1][2]) - a[1][0] * (a[0][1] * a[2][2] - a[2][1] * a[0][2]) + a[2][0] * (a[0][1] * a[1][2] - a[1][1] * a[0][2])) * invdet);

    return true;
}

関連項目[編集 | ソースを編集]