尽管平移值为 0,但 OpenGL ES 对象位置发生变化

OpenGL ES object position changes despite 0 translation value

@Override
public void onDrawFrame(GL10 gl) {
    float[] scratch = new float[16];
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    // Set the camera position (View matrix)
    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
    // Calculate the projection and view transformation
    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);

    if(move_x) x=-tiltx/100;
    else{
        x=0;
        if(side_x) {
            if (tiltx < -0.1f) {
                x = -tiltx / 100;
                move_x = true;
            }
        }

        if(!side_x) {
            if (tiltx > 0.1f) {
                x = -tiltx / 100;
                move_x = true;
            }
        }
    }

    if(move_y) y=-tilty/100;
    else{
        y=0;
        if(side_y){
            if(tilty <-0.1f) {
                y=-tilty/100;
                move_y=true;
            }
        }
        if(!side_y) {
            if(tilty >0.1f) {
                y = -tilty / 100;
                move_y = true;
            }
        }
    }

上面的部分检查是否允许移动,如果不允许它分配 0 来转换值(x 和 y)。比(下方)应用平移,尽管 x 或 y 值为 0,但它会将对象移动得更远一点,这会导致对象部分结束在视图后面。它还会导致触发

if (Math.abs(scratch[12])>=2.4 && move_x)

返回时再次播放,即再次播放声音。

    Matrix.translateM(mBall.mModelMatrix, 0, (float)x*1f, (float)y*1f, 0f);



    // Combine the rotation matrix with the projection and camera view
    // Note that the mMVPMatrix factor *must be first* in order
    // for the matrix multiplication product to be correct.
    Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mBall.mModelMatrix, 0);

    if (Math.abs(scratch[12])>=2.4 && move_x){
        setMyBoolean(true);
        move_x=false;

        if(scratch[12]<0) {
            side_x=false;
            scratch[12]=-(float)2.4;
        }
        else {
            side_x=true;
            scratch[12]=(float)2.4;
            }
        // true - prawa strona, false - lewa
    }

    if (Math.abs(scratch[13])>=1.8 && move_y){
        move_y=false;
        setMyBoolean(true);


        if(scratch[13]<0){
            side_y=true;
            scratch[13]=-(float)1.8;
        }
        else {
            side_y=false;
            scratch[13]=(float)1.8;
        }
        // true - prawa strona, false - lewa
    }

    mBall.draw(scratch);

上面的代码检查物体是否确实撞到了墙,如果撞到了,它会阻止进一步的移动,通过 setMyBoolean 播放声音,最重要的是 - 通过改变 scratch[12] 将物体设置为准确接触墙壁] 和 13 个值。

如上所述,在下一个循环中,对象位置的计算结果不同(尽管平移变量设置为 0),球再次落在墙上。

值得一提的是,它不会在接下来的循环中进一步改变位置。它一直留在墙上,直到我将 phone 倾斜到另一侧触发 if 允许对象从墙上移开。

答案其实很简单,我的方法没有或实际上有效,但只从一帧开始,因为我没有通过平移对象来纠正错误的位置。我所做的只是纠正一次用于绘制对象的矩阵的值。但是由于球记住了它的位置,它在下一帧中仍然会把自己画在墙上。

我为解决此问题所做的工作是,当我检测到球刚好撞到墙上但还没有返回时,调整球的位置。现在通过实际平移对象进行调整,并且每一帧都完成。

这是执行此操作的代码:

if(!move_x) {
        if(side_x) {
            Matrix.translateM(mBall.mModelMatrix, 0, (scratch[12] - (float) 2.4) * 1f, 0, 0f);
            Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mBall.mModelMatrix, 0);
        } else {
            Matrix.translateM(mBall.mModelMatrix, 0, (scratch[12] + (float) 2.4) * 1f, 0, 0f);
            Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mBall.mModelMatrix, 0);
        }
    }

    if(!move_y) {
        if(side_y){
            Matrix.translateM(mBall.mModelMatrix, 0, 0, (1.8f - scratch[13]) * 0.5f, 0f);
            Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mBall.mModelMatrix, 0);
        } else {
            Matrix.translateM(mBall.mModelMatrix, 0, 0, -(1.8f + scratch[13]) * 0.5f, 0f);
            Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mBall.mModelMatrix, 0);
        }
    }