Увеличение масштаба OpenGL ES 2.0 - исчезновение объекта

Мне нравится знать, как правильно увеличить OpenGL ES 2.0. Я успешно нарисовал модель, но она довольно маленькая, и я не могу увеличить эту модель. Что мне нравится, так это масштабирование "сквозь" этой модели.

Модель представляет собой здание с разными этажами - я хотел бы увеличить каждую комнату на каждом этаже. Но либо объект исчезает из-за усеченной видимости, либо я не могу подобраться очень близко к этому объекту.

Я использую жест масштабирования и касания и получаю значение «масштаб» — что мне теперь делать с этим значением?

Что я уже пробовал:

Изменение расстояния в ближней и дальней плоскости и изменение значения 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;

Я загрузил фиктивный проект только с часть OpenGL на Github — на случай, если вы хотите лучше изучить исходный код

Что я имею:

Мой текущий вид

Что мне нужно:

Мой желаемый вид


person Frame91    schedule 11.12.2013    source источник
comment
До сих пор не понимаю, почему меня за это проголосовали. У меня есть четкий вопрос, предоставьте свои требования и просто хочу знать, как я могу этого добиться... Огромная нехватка документации по этой конкретной проблеме...   -  person Frame91    schedule 12.12.2013
comment
Да, кадр согласен с вашей точкой зрения. Многие люди здесь голосуют против, не понимая вопросов.   -  person nilkash    schedule 17.12.2013
comment
Основываясь на ваших фотографиях, вам не нужно увеличивать масштаб — вам просто нужно приблизить камеру. Попробуйте установить супер крошечный возле усеченного конуса. И, судя по сложности вашей модели, я не думаю, что вам нужно настраивать/настраивать ближний усеченный конус. Просто выберите очень маленькое значение и придерживайтесь его. Я не знаю, в каком масштабе ваша модель, но вы можете попробовать разделить высоту стен вашего здания на 1000 или 10 000.   -  person Tenfour04    schedule 07.01.2014
comment
Эй, спасибо! Что вы имеете в виду, когда приближаете камеру? Должен ли я переводить z-значение модели или мне нужно изменить eyeZ ? Вдобавок к этому, когда я меняю ближнюю усеченную пирамиду, например, на 0,0001, вся модель как-то растягивается, и я ничего не вижу четко :/   -  person Frame91    schedule 08.01.2014
comment
Извините, только что увидел ваш комментарий. Я не уверен в особенностях класса Matrix, который вы используете для камеры, но вам просто нужно изменить положение матрицы камеры в направлении z (а не положение модели). Если ваша модель растягивается из-за изменения усечения, это означает, что либо в классе Matrix, либо в вашем вершинном шейдере, либо в коде трансляции вашей модели (который изменяет положение ее вершин) есть ошибка.   -  person Tenfour04    schedule 13.01.2014


Ответы (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);
}

Но это не лучший подход (см. комментарии ниже этого ответа)

person Frame91    schedule 12.12.2013
comment
Хотя это решает вашу проблему, это плохое решение. Что вы там сделали, так это уменьшили поле зрения. LookAt должен помочь, если использовать его правильно. Если ваша модель находится в (0,0,0), а ваш начальный eyeZ равен -1,0, то установка eyeZ на -1,0/масштабирование должна сработать. Как правило, имея текущий вектор глаза eye0 и положение объекта в T0, вы должны реализовать масштабирование как eye = T0 + (eye0-T0)/zoom. - person Matic Oblak; 12.12.2013
comment
Спасибо! утром попробую тмв ;) - person Frame91; 12.12.2013
comment
Эй, Look-At доставляет некоторые проблемы из-за поля зрения... Я не могу сильно приблизить свой объект... он исчезает из-за плоскости ближнего поля (я пытался изменить значение плоскости. .. но это не очень хорошо работает) - person Frame91; 13.12.2013
comment
Ваши NearPlaneDistance и farPlaneDistance определяют отсечение. Лучше всего определить параметры вблизи, вдали и под углом. Затем, чтобы получить эти левые, правые... параметры, вы используете размерность = около * тангенс (угол) * .5. Затем используйте Matrix.frustumM(mProjectionMatrix, 0, -ratio/масштаб * размер, коэффициент/масштаб * размер, -1/масштаб * размер, 1/масштаб * размер, NearPlaneDistance, farPlaneDistance); - person Matic Oblak; 13.12.2013
comment
Привет, я недавно изменил масштабирование. Теперь через предложенный eyeZ ? -1,0/увеличение. Однако я все еще не могу увеличить свою модель (она просто перестает увеличиваться прямо перед тем, как я войду в модель. Я попытался немного увеличить модель, но без разницы. Как я могу это решить?... Я' Мы загрузили пример в следующий репозиторий: github.com/Dalanie/OpenGL- ES/дерево/мастер/зданиеGL - person Frame91; 15.12.2013
comment
Вы не должны масштабировать. Напротив, вы не должны изменять масштаб. Просто переместите камеру ближе и адаптируйте ближнюю плоскость, но сохраните масштабирование (разделив новое и старое соотношение ближней плоскости). - person user1097185; 07.01.2014
comment
Эй, не могли бы вы описать, что вы подразумеваете под адаптацией ближнего самолета? Поменять ближний самолет? И где я должен поддерживать зум - где я должен добавить соотношение? - person Frame91; 08.01.2014

Я смущен вашим "масштабированием" или вы смущены этим. Когда вы перемещаете матрицу просмотра (меняется 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;
}
person user1097185    schedule 07.01.2014
comment
Спасибо за ваш комментарий! Я обновил свой вопрос, чтобы показать вам мою проблему. На самом деле я не знаю, нужно ли мне масштабировать, масштабировать или перемещать камеру для желаемого результата :( Ура! - person Frame91; 07.01.2014
comment
Ну, перевод z работает нормально. Но когда я поворачиваю свою модель, оси меняются местами, так что z не приближается к моему объекту, а, например, сбоку... Если я не поворачиваю, все работает хорошо... - person Frame91; 08.01.2014
comment
Я предполагаю, что это потому, что ваша модель больше не выровнена по оси Z? Не знаете, почему вы поворачиваете модель, а не камеру? - person user1097185; 18.01.2014