android - OpenGL ES 2.0中,如何解决缩放对象消失问题?
高洛峰
高洛峰 2017-04-17 11:29:50
0
1
579

我想知道,在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

高洛峰
高洛峰

拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

reply all(1)
巴扎黑

Answer: Frame91
My method is:

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);
}

Answer: user1097185
I'm not sure what you mean by "zooming". When you move the View matrix, the target is neither zoomed in nor zoomed out, it is just moving the camera. It's true that objects get larger as you move the camera closer, but that's not the effect achieved by zooming. If you want to actually achieve a scaling effect on an object, you need to change the "ratio" in Matrix.frustumM. In this way, the target object will become larger without being obscured by nearby objects. Of course, this will also change your perspective. The larger the zoom, the more it looks like an orthographic projection.
Below is the source code of frustumM. You can see that x and y are only near focus, not far focus. If you want to ensure the zoom effect and a certain viewing angle, you need to zoom in the upper, lower, left, and right proportions according to your expectations. The specific operations are as follows:

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;
}
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!