Симулятор от первого лица с Three.js с использованием стрелок на клавиатуре

Для моего источника, посетите http://jsfiddle.net/fYtwf/

Фон

У меня есть простая 3d-симуляция с использованием three.js, где камера окружена в 3-х измерениях кубами. Эти кубы помогают визуализировать, куда смотрит камера, пока элементы управления представлением не будут закодированы и протестированы. Я хочу создать простое 3D-приложение, в котором камера управляется клавишами вверх, вниз, влево и вправо. Так же, как двигать головой

вопросы

В моем текущем приложении, когда мы обращаемся вперед и начинаем смотреть вверх, мы успешны. Однако, когда мы поворачиваем влево на 90 градусов и нажимаем стрелку вверх... происходит не так. камера увеличивает ось х, но, поскольку мы обращаемся в другом направлении, изменение оси Х в одиночку НЕПРАВИЛЬНО...

Теперь я предполагаю, что это потому, что для вычисления правильных значений для оси z требуется некоторая тригонометрия. Тем не менее, мой триггер не блестящий.

Текущий

Чтобы лучше понять, что я имею в виду, посетите мой jsfiddle: http://jsfiddle.net/fYtwf/

Кнопка ВВЕРХ ТОЛЬКО увеличивает X

Кнопка ВНИЗ ТОЛЬКО уменьшает X

ЛЕВАЯ клавиша ТОЛЬКО увеличивает Y

Правая клавиша ТОЛЬКО уменьшает Y

КлавишаQ ТОЛЬКО увеличивает Z

W ключ ТОЛЬКО уменьшает Z

(Q и W были только закодированы, чтобы попытаться помочь мне понять.)

Из моего текущего понимания, когда я нажимаю клавишу ВВЕРХ, X должен увеличиваться, а ось Z должна изменяться в зависимости от текущей оси Y. Однако я не знаю алгоритм:(

Поэтому X и Z должны быть изменены в коде KEYUP (я думаю, пожалуйста, исправьте меня, если я ошибаюсь)

// setRotateX, getRotateX, setRotateY and getRotateY are extended
// camera functions I wrote so I could work with degrees. Solution
// IS NOT required to use them, they just helped me

switch( key )
{
    case KEYUP:
        if ( camera.getRotateX() < 90 ){ // restrict so they cannot look overhead
            camera.setRotateX( camera.getRotateX() + VIEW_INCREMENT );
        }
        break;

    case KEYDOWN:
        if ( camera.getRotateX() > -90 ){ // restrict so they cannot look under feet
            camera.setRotateX( camera.getRotateX() - VIEW_INCREMENT );
        }
        break;

    case KEYLEFT:
        camera.setRotateY( camera.getRotateY() + VIEW_INCREMENT );
        break;

    case KEYRIGHT:
        camera.setRotateY( camera.getRotateY() - VIEW_INCREMENT );
        break;
}

3 ответа

Решение

Существует несколько решений этой проблемы, но, поскольку вы хотите, чтобы камера вращалась только вверх, вниз, влево и вправо, ответ в этом случае прост.

Вам просто нужно установить порядок камеры Эйлера на "YXZ" примерно так:

camera.rotation.order = "YXZ"; // three.js r.65

Если вы сделаете это, все станет очень интуитивным.

Вот обновленная скрипка: http://jsfiddle.net/fYtwf/3/ (однако эта демоверсия использует r.54)

Как только вы измените camera.rotation.z из его значения по умолчанию zero, все станет очень запутанным. Так что не делай этого.:-)

Three.JS R.65

Хотя это напрямую не исправляет ваш код, я подумал, что упомяну, что Three.js предоставляет два готовых контроллера для навигации в режиме FPS. Они оба используют мышь для поиска и могут двигаться, но должны быть довольно просты, чтобы адаптироваться к внешнему виду клавиатуры и удалять движения, если это необходимо. Они есть:

  • FirstPersonControls
  • PointerLockControls

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

Я создал пример именно того, что вы ищете - камера преследования (которая следует за рамкой) по адресу:

http://stemkoski.github.com/Three.js/

Другие вопросы по тегам