70466
**質問な内容**  
提示画像の最後の行ですがZ軸の値がマイナスになってしまうのですがこれは一番怪しい透視射形行列を間違えたものだと考えるのが一番正しいと思うのですが何を間違えたのでしょうか？

**提示コードと画像について**  
まずスケール、回転、平行移動をしてそこから透視射形行列を使って画面に描画するということをしているコードのGLSLではないCPU計算のコードを作って実証しています。最後のint
main();関数の最後ですコメント///Mは提示コードのシェーダーMに相当する部分のCPU実装コードです。提示画像は最後の出力結果です。

**試したことやったこと**  
行列コードを確認  
行列の掛け算バグを確認

参考サイト: <https://tokoik.github.io/GLFWdraft.pdf> (163ページ)  
Github: <https://github.com/Shigurechan/project2>

[![画像の説明をここに入力](https://i.stack.imgur.com/wkvgz.png)](https://i.stack.imgur.com/wkvgz.png)

```

    #version 400 
    //頂点シェーダー
    
    in vec3  position;//頂点座標
    
    uniform mat4 scale;//スケール行列
    uniform mat4 rotate;//回転行列
    uniform mat4 move;//平行移動行列
    
    uniform mat4 MP;
    
    out vec4 mt;
    
    void main()
    {
        vec4 t = vec4(position,1.0);
        mat4 M = mat4(scale * rotate * move);
    
        //gl_Position = vec4(MP * M * t,1.0);
        gl_Position = vec4(mt,1.0);
    }
    
```

/////////////////////////////////////////////////////////////////////////////////////////////

```

        #include "stdio.h"
    #include <iostream>
    
    float mp[4][4];//透視射形行列
    
    
    //頂点バッファー
    float Vertex[6][4] =
    {
        {-0.5, 0.5, 1.0,1.0},
        {-0.5, -0.5, 1.0,1.0},
        {0.5, -0.5, 1.0,1.0},
    
        {-0.5, 0.5, 1.0,1.0},
        {0.5, 0.5, 1.0,1.0},
        {0.5, -0.5, 1.0,1.0}
    };
    
    //スケール行列
    float scale[4][4] = {
        {1,0,0,0},
        {0,1,0,0},
        {0,0,1,0},
        {0,0,0,1}
    };
    
    
    struct position
    {
    public:
        float x;
        float y;
        float z;
    };
    
    struct position pos;
    
    //回転行列
    float r = 1;
    float rotate[4][4] = {
            (pos.x * pos.x + (1 - cos(r)) + cos(r)),
            (pos.x * pos.y + (1 - cos(r)) + pos.z * sin(r))
        ,(pos.x * pos.z + (1 - cos(r)) - pos.y * sin(r)),0,
    
            (pos.x * pos.x + (1 - cos(r)) + sin(r)),
            (pos.y * pos.y + (1 - cos(r)) + cos(r)),
            (pos.y * pos.z + (1 - cos(r)) + pos.x * sin(r)),0,
    
            (pos.x * pos.z + (1 - cos(r)) - pos.z * sin(r)),
            (pos.y * pos.z + (1 - cos(r)) - pos.x * sin(r)),
            (pos.z * pos.z + (1 - cos(r)) + cos(r)),0,
    };
    
    
    //平行移動
    float mx = 0;
    float my = 0;
    float mz = 0;
    
    float move[4][4] =
    {
        1,0,0,mx,
        0,1,0,my,
        0,0,1,mz,
        0,0,0,1,
    };
    
    ////////////////////////////////////////////////////////////////////////////
    //透視投影変換行列を作る
    void create_matri_mp(float top, float bottom, float left, float right,
                                                                float near, float far, float result[4][4])
    {
        result[0][0] = (2 * near) / (right - left);
        result[0][1] = 0;
        result[0][2] = (right + left) / (right - left);
        result[0][3] = 0;
    
        result[1][0] = 0;
        result[1][1] = (2 * near) / (top - bottom);
        result[1][2] = (top + bottom) / (top - bottom);
        result[1][3] = 0;
    
        result[2][0] = 0;
        result[2][1] = 0;
        result[2][2] = -(far + near) / (far - near);
        result[2][3] = -(2 * far + near) / (far - near);
    
        result[3][0] = 0;
        result[3][1] = 0;
        result[3][2] = -1;
        result[3][3] = 0;
    }
    ///////////////////////////////////////////////////////////////////////////
    //行列を表示
    void print_matrix(const char* str,float mp[4][4])
    {
        printf("name: %s\n",str);
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                printf("[  %.2f   ] , ", mp[i][j]);
            }
            printf("\n");
        }
    }
    
    
    //行列掛け算
    //void mul(float a[4][4], float b[4][4])
    void mul(float a[4][4], float b[4][4], float result[4][4])
    {
        //float result[4][4] = { 0 };
    
        result[0][0] = (a[0][0] * b[0][0]) + (a[0][1] * b[1][0]) + (a[0][2] * b[2][0]) + (a[0][3] * b[3][0]);
    
        result[0][1] = (a[0][0] * b[0][1]) + (a[0][1] * b[1][1]) + (a[0][2] * b[2][1]) + (a[0][3] * b[3][1]);
    
        result[0][2] = (a[0][0] * b[0][2]) + (a[0][1] * b[1][2]) + (a[0][2] * b[2][2]) + (a[0][3] * b[3][2]);
    
        result[0][3] = (a[0][0] * b[0][3]) + (a[0][1] * b[1][3]) + (a[0][2] * b[2][3]) + (a[0][3] * b[3][3]);
    
    
        result[1][0] = (a[1][0] * b[0][0]) + (a[1][1] * b[1][0]) + (a[1][2] * b[2][0]) + (a[1][3] * b[3][0]);
    
        result[1][1] = (a[1][0] * b[0][1]) + (a[1][1] * b[1][1]) + (a[1][2] * b[2][1]) + (a[1][3] * b[3][1]);
    
        result[1][2] = (a[1][0] * b[0][2]) + (a[1][1] * b[1][2]) + (a[1][2] * b[2][2]) + (a[1][3] * b[3][2]);
    
        result[1][3] = (a[1][0] * b[0][3]) + (a[1][1] * b[1][3]) + (a[1][2] * b[2][3]) + (a[1][3] * b[3][3]);
    
    
        result[2][0] = (a[2][0] * b[0][0]) + (a[2][1] * b[1][0]) + (a[2][2] * b[2][0]) + (a[2][3] * b[3][0]);
    
        result[2][1] = (a[2][0] * b[0][1]) + (a[2][1] * b[1][1]) + (a[2][2] * b[2][1]) + (a[2][3] * b[3][1]);
    
        result[2][2] = (a[2][0] * b[0][2]) + (a[2][1] * b[1][2]) + (a[2][2] * b[2][2]) + (a[2][3] * b[3][2]);
    
    
        result[2][3] = (a[2][0] * b[0][3]) + (a[2][1] * b[1][3]) + (a[2][2] * b[2][3]) + (a[2][3] * b[3][3]);
    
        result[3][0] = (a[3][0] * b[0][0]) + (a[3][1] * b[1][0]) + (a[3][2] * b[2][0]) + (a[3][3] * b[3][0]);
    
        result[3][1] = (a[3][0] * b[0][1]) + (a[3][1] * b[1][1]) + (a[3][2] * b[2][1]) + (a[3][3] * b[3][1]);
    
        result[3][2] = (a[3][0] * b[0][2]) + (a[3][1] * b[1][2]) + (a[3][2] * b[2][2]) + (a[3][3] * b[3][2]);
    
        result[3][3] = (a[3][0] * b[0][3]) + (a[3][1] * b[1][3]) + (a[3][2] * b[2][3]) + (a[3][3] * b[3][3]);
    
    
    
        if (true) 
        {
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    printf("[ %.2f ] ", result[i][j]);
                }
    
                printf("\n");
            }
        }
        
    }
    
    void mul_vec3_matrix(float m[4][4],float v[3],float r[3])
    {
        r[0] = (m[0][0] * v[0]) + (m[0][1] * v[1]) + (m[0][2] * v[2]);
    
        r[1] = (m[1][0] * v[0]) + (m[1][1] * v[1]) + (m[1][2] * v[2]);
    
        r[2] = (m[2][0] * v[0]) + (m[2][1] * v[1]) + (m[2][2] * v[2]);
    
    
        printf("\n\n");
        for (int j = 0; j < 3; j++)
        {
            printf("[ %.2f ] ", r[j]);
        }
        printf("\n");
    
    }
    
    
    
    
    
    
    int main()
    {
        create_matri_mp(1.0f,-1.0f,-1.0f,1.0f,1.0,10.f,mp);
    //    print_matrix("透視射形",mp);
    
    
        
        float t[4][4];
        mul(rotate,move,t);
        printf("\n\n\n\n\n");
        float t2[4][4];//M
        mul(scale, t, t2);
    
        float t3[4];
    
        mul_vec3_matrix(t2, Vertex[0], t3);
        float t4[4];
    
    
        mul_vec3_matrix(mp,t3,t4);
    
    
    
    
    
        return 0;
    }
    
```
CC BY-SA 4.0
2020-09-16T08:42:07.697
70444
2020-09-17T01:26:19.873
2020-09-16T11:18:48.457
question
c++ opengl
透視射形行列のどこが間違えているのか知りたい
正直言って理解できていないことを理解できないまま実装しようとしている印象を受けます。何が正しいのか理解できずに先に進もうとしても無理。第三者に「あなたと同じことに興味を持て」と言ってもそんなのシランです。まあ単純に
[c](/questions/tagged/c "'c' のタグが付いた質問を表示") のプログラミング技術面だけ指摘するなら

提示 `roatate[4][4]`
行列は大域変数ですが、要素１６個に対して初期値は１２個しかないです。たぶんそのままでは全く意味をなさないはず。また、この変数はプログラムが開始した時点で初期化されます。その後代入等で値を変えている様子がありません。
`pos` の初期値は `0` つまり原点で、同様 `r` の初期値は `1` radian
です。初期値の数を合わせた＋式が間違っていないとしても原点の固定角度回転ですから無意味。

同じことが `move[4][4]` にも言えます（初期化の時点での値をそのまま使っても無意味：まあこの変数は現状使われていないわけですが）

プログラムは数学とはいささか異なります。数式上のどの値（ `θ`
とか）が変数か定数かはプログラムに実装する上では極めて重要で、変数の値が変わった後は行列自体の再計算が必要です（が、現状まったくそうなっていない）
CC BY-SA 4.0
2020-09-17T01:26:19.873
70466
2020-09-17T01:26:19.873
8589
70444
answer