Симулятор от первого лица с 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
Я бы порекомендовал последний в качестве отправной точки, потому что он довольно прост, и первый смущающе имеет выглядящий код дважды, вероятно, как артефакт из старых функций.
Я создал пример именно того, что вы ищете - камера преследования (которая следует за рамкой) по адресу: