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

我想知道,在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教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

全員に返信(1)
巴扎黑

答: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
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!