Нарисовать выровненный квадрант камеры в правильном мировом положении? - PullRequest
0 голосов
/ 19 сентября 2018

У меня проблемы с прорисовкой четырехугольника, обращенного к неподвижной (но повернутой) ортографической камере.Ортографическая камера отображает трехмерный мир в изометрической проекции.Теперь мне нужно разместить изомерные спрайты в мире, чтобы в конечном итоге эти квады должны были отображаться в правильном мировом положении.Но в настоящее время я пытаюсь просто нарисовать один в центре мира.

// FloorObject just holds the UV coordinates to be used.
public void addBillboard(FloorObject floorObject) {
    Vector3 direction =  new Vector3(1, 0, 0).nor();
    Vector3 cameraDirection = cam.direction;//cam.position.cpy().sub(new Vector3(0, 0, 0)).nor();

    Vector3 leftRight = direction;

    float dot = direction.cpy().dot(cameraDirection);

    cam.normalizeUp();
    Vector3 updown = cam.up;//new Vector3(0, 1, 0);

    if (Math.abs(dot) < 1f) {
        updown = direction.cpy().crs(cameraDirection);
    }
    updown.nor();

    Vector3 position = new Vector3(0, 0, 0);

    Vector3 bottomLeft = position.cpy().add(updown).sub(leftRight);
    Vector3 topLeft = position.cpy().sub(updown).sub(leftRight);
    Vector3 bottomRight = position.cpy().add(updown).add(leftRight);
    Vector3 topRight = position.cpy().sub(updown).add(leftRight);

    // Adding verts to the buffer.

    // Bottom left
    verts[vi++] = bottomLeft.x;
    verts[vi++] = bottomLeft.y;
    verts[vi++] = bottomLeft.z;
    verts[vi++] = floorObject.getU();
    verts[vi++] = floorObject.getV2();
    verts[vi++] = 1;

    // Bottom right
    verts[vi++] = bottomRight.x;
    verts[vi++] = bottomRight.y;
    verts[vi++] = bottomRight.z;
    verts[vi++] = floorObject.getU2();
    verts[vi++] = floorObject.getV2();
    verts[vi++] = 1;

    // Top left
    verts[vi++] = topLeft.x;
    verts[vi++] = topLeft.y;
    verts[vi++] = topLeft.z;
    verts[vi++] = floorObject.getU();
    verts[vi++] = floorObject.getV();
    verts[vi++] = 1;

    // Top right
    verts[vi++] = topRight.x;
    verts[vi++] = topRight.y;
    verts[vi++] = topRight.z;
    verts[vi++] = floorObject.getU2();
    verts[vi++] = floorObject.getV();
    verts[vi++] = 1;

}

Используя это в моей изометрической проекции, квад поворачивается на 27,5 градусов.При использовании перспективной камеры она вращается повсюду.Я действительно только хочу, чтобы изометрическая текстура отображалась в правильном мировом положении с помощью этой изометрической камеры.

В случае, если это имеет значение, мне нужно рисовать эти спрайты в определенном порядке, в зависимости от другой геометрии всцена.Поэтому я вызываю этот метод по порядку (задом наперед) всякий раз, когда мне нужно нарисовать изометрический спрайт, и он добавляется в VertexBuffer в правильном порядке.

1 Ответ

0 голосов
/ 20 сентября 2018

Я придумал очень короткое (в коде) решение.Принимая во внимание матрицу вида камеры, я не очень разбираюсь в матрицах, но они по существу содержат вращение, масштаб и преобразование.Таким образом, в моем последнем примере я создал 2 вектора «leftRight» и «upDown» и переименовал их в «right» и «up», представляющие направление камеры вправо и вверх в представлении о мире, также часто называемое представлением модели.Вот как я получил правильные значения из матрицы вида камеры.

    right.x = modelview.val[0];
    right.y = modelview.val[4];
    right.z = modelview.val[8];

    up.x = modelview.val[1];
    up.y = modelview.val[5];
    up.z = modelview.val[9];

Он просто ищет значения в массиве.Я попробовал это очень раньше, но использовал некорректные индексы поиска.Имея их, математика для преобразования вершины довольно проста.

    float size = 1.4142135624f;

    Vector3 bottomLeft = position.cpy().sub(right.cpy().scl(size * .5f));
    Vector3 bottomRight = position.cpy().add(right.cpy().scl(size * .5f));
    Vector3 topRight = position.cpy().add(right.cpy().scl(size * .5f)).add(up.cpy().scl(size * 2));
    Vector3 topLeft = position.cpy().sub(right.cpy().scl(size * .5f)).add(up.cpy().scl(size * 2));

Так как мои квадратные квадраты имеют размер 1x1, мне нужно сделать Пифагор 1.414.., так как он должен заполнить полную плитку.Затем я вычисляю положение каждой вершины, так как мне нужно было расположить нижний центр четырехугольника в точном мировом положении, я умножаю размер на .5, и мои рекламные щиты должны быть в два раза больше по высоте, поэтому я умножаю размер навектор увеличения на 2. Чтобы сделать это быстрее, создайте для этого 2 константы (ширину и высоту), чтобы умножения не понадобились.Затем, когда они будут рассчитаны, я могу просто группировать свои вершины, как обычно.

    // Bottom left
    verts[vi++] = bottomLeft.x;
    verts[vi++] = bottomLeft.y;
    verts[vi++] = bottomLeft.z;
    verts[vi++] = floorObject.getU();
    verts[vi++] = floorObject.getV2();
    verts[vi++] = 1;

    // Bottom right halfway
    verts[vi++] = bottomRight.x;
    verts[vi++] = bottomRight.y;
    verts[vi++] = bottomRight.z;
    verts[vi++] = floorObject.getU2();
    verts[vi++] = floorObject.getV2();
    verts[vi++] = 1;

    // Top left
    verts[vi++] = topLeft.x;
    verts[vi++] = topLeft.y;
    verts[vi++] = topLeft.z;
    verts[vi++] = floorObject.getU();
    verts[vi++] = floorObject.getV();
    verts[vi++] = 1;

    // Top right halway
    verts[vi++] = topRight.x;
    verts[vi++] = topRight.y;
    verts[vi++] = topRight.z;
    verts[vi++] = floorObject.getU2();
    verts[vi++] = floorObject.getV();
    verts[vi++] = 1;
...