围绕z轴旋转漂移

时间:2012-08-30 12:13:19

标签: java android opengl-es opengl-es-2.0

在应用程序中,在尝试使用触摸旋转对象时,我注意到某个时间后对象位置的漂移(未应用任何翻译!!)。旋转仅在z轴附近并且完美地起作用,但是仅在几次旋转之后才发生漂移。

ds 将用于进行翻译(使用上下按钮)。

如果我更正了,

_uNozzleCentreMatrix_ModelMatrixNozzle 将使用 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);

1 个答案:

答案 0 :(得分: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