Увеличить OpenGL ES 2.0 - объект исчезает
Мне нравится знать о том, как правильно увеличить масштаб OpenGL ES 2.0
, Я успешно нарисовал модель, но она довольно маленькая, и я не могу увеличить эту модель. Что мне нравится, так это масштабировать "сквозь" эту модель.
Модель представляет собой здание с разными этажами - я хотел бы увеличить каждую комнату на каждом этаже. Но либо объект исчезает из-за усеченного вида, либо я не могу подойти очень близко к этому объекту.
Я использую жест zoom-touch и получаю значение "scale" - что мне теперь делать с этим значением?
Что я пробовал до сих пор:
Изменение расстояния в ближней и дальней плоскостях и изменение значения eyeZ-значения в Matrix.setLookAtM(....), но единственное, чего я добиваюсь - это уменьшение масштаба... Оно исчезает при увеличении через некоторое время... Так что я Я не могу увеличить некоторые специальные части ("ЭТО" далеко....)
Как мне этого добиться?
Таким образом, самой большой проблемой является ближняя плоскость в сочетании с масштабированием с помощью eyeZ-Value. Это просто не работает. Если я увеличу масштаб, объект исчезнет из-за ближней плоскости. Но я не вижу никакой логики за этим.
В настоящее время я использую:
/*
* Set the camera position (View matrix)
*/
Matrix.setLookAtM(mViewMatrix, offset, eyeX, eyeY, eyeZ / mZoomLevel,
centerX, centerY, centerZ, upX, upY, upZ);
где mZoomLevel - это коэффициент, который я получаю при помощи onTouch-Zooming.
Вся моя Матрица-Операции показана здесь:
@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;
Что я имею:
Что мне нужно:
2 ответа
Одно из моих решений (работает не очень хорошо):
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);
}
Но это не лучший подход (см. Комментарии ниже этого ответа)
Я запутался в вашем "увеличении" или вы запутались в этом. Когда вы перемещаете матрицу просмотра (изменяя eyeZ), вы не увеличиваете или уменьшаете масштаб, вы просто перемещаете камеру. Да, перемещение камеры ближе к объекту сделает его больше (в случае перспективной проекции), но это не увеличение. Вы увеличиваете, изменяя фокусное расстояние или угол обзора камеры. Вы меняете "проницательность" своей камеры. Точно так же, как если бы у вас была настоящая камера, просто идти к объекту съемки отличается от использования зума камеры (при условии, что у нее есть механический зум).
Чтобы действительно увеличить что-то (если это действительно то, что вы хотите), вам нужно изменить "соотношение" в Matrix.frustumM. Таким образом, вы можете заставить объекты "становиться больше" на экране, не беспокоясь об обрезании объекта ближней плоскостью. Однако это также изменит перспективу. Чем больше вы увеличиваете, тем больше будет выглядеть орфографическая проекция.
Я думаю, что вы пытаетесь достичь летать внутри модели здания. Для этого вам не нужно динамически регулировать зум камеры. Но вам нужно отрегулировать переднюю и конечную плоскости.
Я думаю, я знаю, что является источником вашего замешательства. Когда вы изменяете ближнюю плоскость усеченного конуса, но сохраняете фиксированное соотношение, вы фактически изменяете масштаб и угол обзора. Поскольку значения x и y матрицы проекции рассчитываются по ближней плоскости, деленной на левый / правый и верхний / нижний. Левый, правый и верхний, нижний в Matrix.frustumM фактически являются размерами ближней плоскости.
Вот исходный код FrustumM. Вы можете видеть, что x и y, являющиеся фокусной точкой, вычисляются с использованием только ближней плоскости, а не дальней плоскости. Если вы хотите сохранить масштаб или угол обзора и изменить ближнюю плоскость, вам придется умножить левую, правую (соотношение в вашем случае) и верхнюю, нижнюю (1 в вашем случае) на соотношение между исходной близкой глубиной и новая близкая глубина.
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;
}