首頁  >  問答  >  主體

android - OpenGL ES 2.0中,如何解决缩放对象消失问题?

我想知道,在OpenGL ES 2.0中,如何正确使用缩放(zoom)功能。目前,我已经成功的创建了一个model,但是由于尺寸太小,无法对其进行缩放处理,我想要实现一种“内部”("through")的缩放效果。
这里的model由不同的层组成,我想要将每一层的room都进行缩放处理,但无论怎么操作,对象都会无故消失,我现在用的手势是zoom-touch,怎么样才能解决这个问题?
已尝试的操作:
改变near-plane和far-plane距离,改变Matrix.setLookAtM(....)中的eyeZ-Value,但是我只能实现缩小的效果,它会在稍放大之后消失,所以我无法对特定部分进行放大。
我的实现方法:
目前,最大的问题就是用eyeZ-Value,无法将near-plane进行适当的缩放操作,如果进行放大处理,对象就会消失,但是,就目前使用的代码而言,我没发现有什么问题。
我现在用的是:

/*
 * Set the camera position (View matrix)
 */
Matrix.setLookAtM(mViewMatrix, offset, eyeX, eyeY, eyeZ / mZoomLevel,
                  centerX, centerY, centerZ, upX, upY, upZ);

这里的mZoomLevel是完成onTouch-Zooming的一个因素。
对于Matrix-Operations,我的做法是:

@Override
public void onDrawFrame(GL10 unused) {

LoggerHelper.calculateFPS();

/*
 * Draw background color
 */
 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

/*
 * scale model down to smaller values
 */
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.scaleM(mModelMatrix, 0, model3d.getRatio() * scaleFactor,
                model3d.getRatio() * scaleFactor, model3d.getRatio()
                                * scaleFactor);

/*
 * rotate and translate model in dependence to the user input
 */
Matrix.translateM(mModelMatrix, 0, translateX, translateY, translateZ);
Helper.rotateModel(mModelMatrix, rotationX, rotationY, rotationZ, true,
                model3d.getWidth(), model3d.getLength(), model3d.getHeight());

/*
 * Set the camera position (View matrix)
 */
Matrix.setLookAtM(mViewMatrix, offset, eyeX, eyeY, eyeZ / mZoomLevel,
                centerX, centerY, centerZ, upX, upY, upZ);

/*
 * combine the model with the view matrix
 */
Matrix.multiplyMM(mMVMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);

/*
 * this projection matrix is applied to object coordinates in the
 * onDrawFrame() method
 */
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, 1, -1,
                nearPlaneDistance, farPlaneDistance);

/*
 * Calculate the projection and view transformation
 */
float[] mMVPMatrix = new float[16];
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVMatrix, 0);

/*
 * all the drawing stuff inside the model-object (otherwise
 * translation/rotation wouldn't affect every object)
 */
model3d.draw(mMVPMatrix);
}

下面是一些重要的变量:

private float nearPlaneDistance = 1f;
private float farPlaneDistance = 200f;
private float eyeZ = -1;

得到的效果,

需要的效果:

原问题:Zoom in OpenGL ES 2.0 - object disappearing

高洛峰高洛峰2763 天前582

全部回覆(1)我來回復

  • 巴扎黑

    巴扎黑2017-04-17 11:31:50

    答:Frame91
    我的方法是:

    public void setZoom(float zoom) {
        // this projection matrix is applied to object coordinates
        // in the onDrawFrame() method
        float ratio = (float) width / height;
        Matrix.frustumM(mProjectionMatrix, 0, -ratio / zoom, ratio / zoom, -1
                / zoom, 1 / zoom, nearPlaneDistance, farPlaneDistance);
    }
    

    答:user1097185
    我不太清楚你所提到的"zooming"到底是什麼意思。當你移動View matrix時,對目標既沒有放大,也沒有縮小,只是在移動相機而已。的確,將鏡頭移近,物體會變大,但那不是由縮放實現的效果。如果想要真正對某個物體實現縮放效果,你需要改變Matrix.frustumM中的"ratio"。這樣,目標物件會變得更大,而不會被近處物體遮擋消失。當然,這也會改變你的視角。縮放比例越大,看起來越像正投影。
    下面是frustumM的源碼,可以看到,x和y只是近焦點,而不是遠焦點。如果想要確保縮放效果和一定的觀察角度,你需要對上、下、左、右按照你的預期進行適當比例的放大,具體操作如下:

    public static void frustumM(float[] m, int offset,
            float left, float right, float bottom, float top,
            float near, float far) {
        if (left == right) {
            throw new IllegalArgumentException("left == right");
        }
        if (top == bottom) {
            throw new IllegalArgumentException("top == bottom");
        }
        if (near == far) {
            throw new IllegalArgumentException("near == far");
        }
        if (near <= 0.0f) {
            throw new IllegalArgumentException("near <= 0.0f");
        }
        if (far <= 0.0f) {
            throw new IllegalArgumentException("far <= 0.0f");
        }
        final float r_width  = 1.0f / (right - left);
        final float r_height = 1.0f / (top - bottom);
        final float r_depth  = 1.0f / (near - far);
        final float x = 2.0f * (near * r_width);
        final float y = 2.0f * (near * r_height);
        final float A = 2.0f * ((right + left) * r_width);
        final float B = (top + bottom) * r_height;
        final float C = (far + near) * r_depth;
        final float D = 2.0f * (far * near * r_depth);
        m[offset + 0] = x;
        m[offset + 5] = y;
        m[offset + 8] = A;
        m[offset +  9] = B;
        m[offset + 10] = C;
        m[offset + 14] = D;
        m[offset + 11] = -1.0f;
        m[offset +  1] = 0.0f;
        m[offset +  2] = 0.0f;
        m[offset +  3] = 0.0f;
        m[offset +  4] = 0.0f;
        m[offset +  6] = 0.0f;
        m[offset +  7] = 0.0f;
        m[offset + 12] = 0.0f;
        m[offset + 13] = 0.0f;
        m[offset + 15] = 0.0f;
    }
    

    回覆
    0
  • 取消回覆