31

タッチイベントへの応答Androidチュートリアルに関する質問で別のユーザーを支援した後、ソースコードをダウンロードしましたが、見たものにかなり戸惑いました。チュートリアルでは、行ベクトルと列ベクトルのどちらを使用するかを決定できないようで、すべてが混乱しているように見えます。

Android Matrixページで、彼らは、彼らの慣習は、OpenGLに典型的なcolumn-vector/column-majorであると主張しています。

私は正しいですか、それとも私が欠けているものがありますか?関連する部分は次のとおりです。

mProjMatrix * mVMatrixを乗算して、MVPMatrixを作成することから始めます。ここまでは順調ですね。

    // Set the camera position (View matrix)
    Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    // Calculate the projection and view transformation
    Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0)

次に、MVPMatrixの左側に回転を追加していますか?これは少し奇妙に思えます。

    // Create a rotation for the triangle
    Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);

    // Combine the rotation matrix with the projection and camera view
    Matrix.multiplyMM(mMVPMatrix, 0, mRotationMatrix, 0, mMVPMatrix, 0)

転置されていない順序でアップロードします。

    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);

最後に、シェーダーで、ベクトル*行列の乗算?

    // the matrix must be included as a modifier of gl_Position
    "  gl_Position = vPosition * uMVPMatrix;" 

これをすべて足し合わせると、次のようになります。

gl_Position = vPosition * mRotation * mProjection * mView;

これは私の想像力の範囲では正しくありません。ここで何が起こっているのかわからないという説明はありますか?

4

5 に答える 5

26

そのOpenGLチュートリアルを書いた人として、私はサンプルコードが正しくないことを確認できます。具体的には、シェーダーコードの要素の順序を逆にする必要があります。

"  gl_Position = uMVPMatrix * vPosition;"

回転行列の適用に関しては、回転が最後の因子になるように、因子の順序も逆にする必要があります。経験則では、行列は右から左の順序で適用され、回転が最初に適用されるため(「MVP」の「M」部分)、右端のオペランドである必要があります。さらに、Ian Ni-Lewisが推奨するように、この計算にはスクラッチマトリックスを使用する必要があります(以下の彼のより完全な回答を参照してください)。

float[] scratch = new float[16];
// Combine the rotation matrix with the projection and camera view
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);

この問題に注意を促してくれてありがとう。できるだけ早くトレーニングクラスとサンプルコードを修正します。

編集:この問題は、ダウンロード可能なサンプルコードとOpenGL ESトレーニングクラスで修正され、要素の正しい順序に関するコメントが含まれています。フィードバックをありがとう、皆さん!

于 2012-09-06T23:15:48.937 に答える
10

チュートリアルは正しくありませんが、多くの間違いは互いに打ち消し合うか、この非常に限られた状況では明らかではありません((0,0)を中心とする固定カメラ、Zを中心とした回転のみ)。回転は逆方向ですが、それ以外の場合は正しく見えます。(なぜそれが間違っているのかを確認するには、ささいなカメラを試してください。たとえば、eyeとlookAtをy = 1に設定します。)

これをデバッグするのが非常に困難になった理由の1つは、Matrixメソッドが入力に対してエイリアス検出を行わないことです。チュートリアルコードでは、入力と結果の両方として同じ行列を使用してMatrix.multiplyMMを呼び出すことができるように見えます。これは真実ではありません。ただし、実装は一度に1つの列を乗算するため、左側を再利用する場合よりも、右側を再利用する場合(mMVPMatrixがrhsと結果である現在のコードのように)に問題があることは明らかではありません。 。左側の各列は、結果の対応する列が書き込まれる前に読み取られるため、LHSが上書きされても出力は正しくなります。ただし、右側が結果と同じである場合、最初の列は読み取りが完了する前に上書きされます。

したがって、チュートリアルコードは、ある種の極大値にあります。それは機能しているように見えます。何かを変更すると、見事に壊れます。これは、見た目が間違っていると信じさせるものですが、それは正しいかもしれません。;-)

とにかく、ここに私が意図した結果であると思うものを取得するいくつかの置換コードがあります。

Javaコード:

@Override
public void onDrawFrame(GL10 unused) {
    float[] scratch = new float[16];

    // Draw background color
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

    // Set the camera position (View matrix)
    Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    // Calculate the projection and view transformation
    Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);

    // Draw square
    mSquare.draw(mMVPMatrix);

    // Create a rotation for the triangle
    Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, 1.0f);

    // Combine the rotation matrix with the projection and camera view
    Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);

    // Draw triangle
    mTriangle.draw(scratch);
}

シェーダーコード:

gl_Position =  uMVPMatrix * vPosition;

注意:これらの修正により、投影は正しくなりますが、回転方向も逆になります。これは、元のコードが変換を間違った順序で適用したためです。このように考えてください。オブジェクトを時計回りに回転させるのではなく、カメラを反時計回りに回転させていました。カメラではなくオブジェクトに回転が適用されるように操作の順序を修正すると、オブジェクトは反時計回りに動き始めます。間違っているのはマトリックスではありません。マトリックスの作成に使用された角度です。

したがって、「正しい」結果を得るには、マングルの符号を反転する必要もあります。

于 2012-09-07T02:36:15.553 に答える
2

私はこの問題を次のように解決しました:

@Override
public void onDrawFrame(GL10 unused) {      
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -1f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);        

    Matrix.setRotateM(mModelMatrix, 0, mAngle, 0, 0, 1.0f);
    Matrix.translateM(mModelMatrix, 0, 0.4f, 0.0f, 0);

    mSquare.draw(mProjMatrix,mViewMatrix,mModelMatrix);
}

@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
    ...  
    Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 1, 99);

}

class Square {

    private final String vertexShaderCode =
        "uniform mat4 uPMatrix; \n" +
        "uniform mat4 uVMatrix; \n" +
        "uniform mat4 uMMatrix; \n" +

        "attribute vec4 vPosition; \n" +
        "void main() { \n" +
        "  gl_Position = uPMatrix * uVMatrix * uMMatrix * vPosition; \n" +
        "} \n";

    ...

    public void draw(float[] mpMatrix,float[] mvMatrix,float[]mmMatrix) {

        ...

        mPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uPMatrix");
        mVMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uVMatrix");
        mMMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMMatrix");

        GLES20.glUniformMatrix4fv(mPMatrixHandle, 1, false, mpMatrix, 0);
        GLES20.glUniformMatrix4fv(mVMatrixHandle, 1, false, mvMatrix, 0);
        GLES20.glUniformMatrix4fv(mMMatrixHandle, 1, false, mmMatrix, 0);

        ...
    }
}
于 2013-05-04T08:36:35.193 に答える
1

私は同じ問題に取り組んでいます、そしてそれは私が見つけたものです:

Joeのサンプルは
、シェーダーコードの要素の順序を含めて、正しいと思います。

gl_Position = vPosition * uMVPMatrix;

逆の係数の順序で三角形を回転させようとするだけで確認するには、三角形を90度の消失点まで伸ばします。

本当の問題はsetLookAtM関数にあるようです。
Joeのサンプルパラメータは次のとおりです。

Matrix.setLookAtM(mVMatrix, 0,
     0f, 0f,-3f,   0f, 0f, 0f,   0f, 1f, 0f );

これも完全に論理的です。
ただし、結果のビューマトリックスは私には奇妙に見えます。

-1  0  0  0
 0  1  0  0
 0  0 -1  0
 0  0 -3  1

ご覧のとおり、最初のメンバーは–1で
あるため、このマトリックスはX座標を反転します。これにより、画面が左右に反転します。
Zオーダーも逆になりますが、ここではX座標に注目しましょう。

setLookAtM関数も正しく機能していると思います。
ただし、MatrixクラスはOpenGLの一部ではないため、他の座標系を使用できます
。たとえば、Y軸が下を向いている通常の画面座標です。
これは単なる推測であり、実際には確認していません。

考えられる解決策:
望ましいビューマトリックスを手動で作成でき
ます。コードは次のとおりです。

Matrix.setIdentityM(mVMatrix,0);
mVMatrix[14] = -3f;

または、setLookAtM関数にカメラ座標を逆にして0、0、+ 3(–3ではなく)を与えることで、setLookAtM
関数をだまそ うとすることができます。

Matrix.setLookAtM(mVMatrix, 0,
     0f, 0f, 3f,   0f, 0f, 0f,   0f, 1f, 0f );

結果のビューマトリックスは次のようになります。

1  0  0  0
0  1  0  0
0  0  1  0
0  0 -3  1

それがまさに私たちが必要としていることです。
これで、カメラは期待どおりに動作し
、サンプルは正しく機能します。

于 2012-10-04T06:19:26.927 に答える
0

三角形を移動しようとしたときの次の場合を除いて、現在更新されているAndroidサンプルコードを使用した他の提案は機能しませんでした。

次のリンクに答えが含まれています。それを見つけるために1日以上かかりました。この投稿を何度も見たので、他の人を助けるためにここに投稿します。OpenGLESAndroidマトリックス変換

于 2013-11-20T22:32:55.657 に答える