1

アプリケーションで、タッチを使用してオブジェクトを回転させようとしているときに、しばらくしてオブジェクトの位置がずれていることに気付きました (変換が適用されていません!!)。回転は z 軸のみであり、完全に機能しますが、ドリフトは数回転後にのみ発生します。

ds will be used翻訳用 (上下ボタンを使用)。

_uNozzleCentreMatrixそして_ModelMatrixNozzle will use ds、私がこれを修正した場合。

private static final float[] _uNozzleCentre     = new float[]{0.0f, 0.333605f, 0.0f, 1.0f};
protected static float[] _uNozzleCentreMatrix   = new float[4];

public void onSurfaceChanged(GL10 gl, int width, int height) {
    gl.glViewport(0, 0, width, height);
    float ratio = (float) width / height;
    Matrix.setLookAtM(GLES20Renderer._ViewMatrix, 0, 0, 0, 7f, 0, 0, 0, 0, 1, 0);
    Matrix.frustumM(GLES20Renderer._ProjectionMatrix, 0, -ratio, ratio, -1, 1, 2, 8);
    Matrix.setIdentityM(GLES20Renderer._ModelMatrixNozzle, 0);
}
private static void updateModel(int upDown, float xAngle, float yAngle, float zAngle) {
    //ds                = GLES20Renderer._upDown - GLES20Renderer._lastUpDown;
    ds = 0; // ds changes with button up-down, but now it is made 0, so button up-down will not affect it
    Matrix.multiplyMV(GLES20Renderer._uNozzleCentreMatrix, 0, GLES20Renderer._ModelMatrixNozzle, 0, GLES20Renderer._uNozzleCentre, 0);
    if(Math.abs(ds) > 0) {
    } else {
        if(GLES20Renderer._zAngle >= 360) {
            GLES20Renderer._zAngle = GLES20Renderer._zAngle - 360;
        }
        if(GLES20Renderer._zAngle <= -360) {
            GLES20Renderer._zAngle = GLES20Renderer._zAngle + 360;
        }
        Matrix.translateM(GLES20Renderer._ModelMatrixNozzle, 0, GLES20Renderer._uNozzleCentreMatrix[0], GLES20Renderer._uNozzleCentreMatrix[1], 0);
        Matrix.rotateM(GLES20Renderer._ModelMatrixNozzle, 0, GLES20Renderer._zAngle, 0, 0, 1);
        Matrix.rotateM(GLES20Renderer._ModelMatrixNozzle, 0, -GLES20Renderer._lastZAngle, 0, 0, 1);
        Matrix.translateM(GLES20Renderer._ModelMatrixNozzle, 0, -GLES20Renderer._uNozzleCentreMatrix[0], -GLES20Renderer._uNozzleCentreMatrix[1], 0);
    }
    Matrix.multiplyMM(GLES20Renderer._MVPMatrixNozzle, 0, GLES20Renderer._ViewMatrix, 0, GLES20Renderer._ModelMatrixNozzle, 0);
    Matrix.multiplyMM(GLES20Renderer._MVPMatrixNozzle, 0, GLES20Renderer._ProjectionMatrix, 0, GLES20Renderer._MVPMatrixNozzle, 0);

    GLES20Renderer._lastZAngle = zAngle;
}

ダウンロード用の APK:

http://www.pixdip.com/opengles/rotation/rotation.apk

(ドリフトを早期に観察するために、左端から右に長い水平領域をスワイプしてみてください。しばらくお待ちください!ドリフトが発生するまでに 20 秒かかる場合があります)

それが起こらなかった人のために、ここに自動化された apk があります: http://www.pixdip.com/opengles/rotation/automatic.apk

およびコードの編集部分:

        Matrix.translateM(GLES20Renderer._ModelMatrixNozzle, 0, GLES20Renderer._uNozzleCentreMatrix[0], GLES20Renderer._uNozzleCentreMatrix[1], 0);
        Matrix.rotateM(GLES20Renderer._ModelMatrixNozzle, 0, GLES20Renderer._zAngle, 0, 0, 1);
        //Matrix.rotateM(GLES20Renderer._ModelMatrixNozzle, 0, -GLES20Renderer._lastZAngle, 0, 0, 1);
        Matrix.translateM(GLES20Renderer._ModelMatrixNozzle, 0, -GLES20Renderer._uNozzleCentreMatrix[0], -GLES20Renderer._uNozzleCentreMatrix[1], 0);
4

1 に答える 1

0

行列スタックが原因で、浮動小数点エラーが蓄積されることがあります。

これは、いくつかの重要な変換に別の行列を使用することで削除できます。

private static float[] _TMatrix = new float[16];
private static float[] _ModelMatrix = new float[16];
Matrix.setIdentity(Renderer._ModelMatrix);
Matrix.setIdentity(Renderer._TMatrix);
Matrix.translate(Renderer._ModelMatrix, xmov,ymov,0);
Matrix.translate(Renderer._TMatrix, -xmov,-ymov,0);
Matrix.multiply(Renderer._ModelMatrix, Renderer._TMatrix, Renderer._ModelMatrix);
// will result in an identity model matrix, without any floating point errors
于 2012-08-31T13:56:00.290 に答える