我想知道,在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
巴扎黑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;
}