Как заставить камеру двигаться в направлении, в котором она смотрит в Java?

Мне нужен способ (в java), чтобы вычислить, в каком направлении моя камера будет двигаться вперед по осям x и z, в зависимости от направления, в котором смотрит моя камера (рыскание), а для y (вертикальная ось) - шага. Я делаю свой собственный игровой движок и свою камеру.

Когда все значения по умолчанию равны нулю, перемещение камеры правильно направляет все движения вдоль положительной оси z. Однако, когда я панорамирую камеру влево или вправо (тем самым изменяя рыскание), камера по-прежнему перемещается только вдоль оси z ... Итак, как мне рассчитать изменение направления по осям x, y и z?

Диапазон значений по рысканью: 0 (юг), 45 (юго-запад), 90 (запад), 135 (северо-запад), 180 (север), 225 (северо-восток), 270 (восток), 315 (юго-восток) и обратно на 360 (юг, то же, что и 0).

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

South = x, y, z+
SouthWest = x+, y, z+
West = x+, y, z
NorthWest = x+, y, z-
North = x, y, z-
NorthEast = x-, y, z-
East = x-, y, z
SouthEast = x-, y, z+

Диапазон значений высоты звука: 0,0 (средний), 100,0 (полностью вверх) и -100,0 (полностью вниз).

Если мне нужно опубликовать код, я могу, но это может быть сложно. Я надеюсь, что у меня есть какой-то смысл, чтобы кто-то мог мне помочь!


person Brian_Entei    schedule 10.08.2013    source источник


Ответы (1)


Предположим, вы хотите переместить камеру в направлении y на расстояние k. Для простоты я конвертирую ваши направления в углы, где 0,0 представляет правое, Pi / 2 представляет вверх, Pi представляет левое, 3 * Pi / 2 представляет вниз и так далее.

РЕДАКТИРОВАТЬ: Как вы говорите, y камеры будет зависеть только от высоты тона. X и z будут зависеть как от рыскания, так и от тангажа.

Вы можете вычислить новые x, y и z следующим образом:

float y = // Yaw angle
float p = // Pitch angle
float k = // Move distance

float xzLength = cos(p) * k;
float dx = xzLength * cos(y);
float dz = xzLength * sin(y);
float dy = k * sin(p);

// Update your camera:
camera.x += dx;
camera.y += dy;
camera.z += dz;

Очевидно, рыскание и тангаж не меняются, поэтому вам не нужно их обновлять.

person Lake    schedule 10.08.2013
comment
Отлично, я займусь этим, как только смогу! Только один быстрый вопрос: если бы я действительно хотел, чтобы шаг (движение вверх и вниз) учитывался в значениях x и z для «летающей» камеры, как бы я это сделал? - person Brian_Entei; 10.08.2013
comment
Я думаю, что в моем решении шаг фактически разложен на x и z, поскольку вы можете видеть, что xzLength зависит от p и dz, dx зависит от него, я неправильно понимаю ваш вопрос? - person Lake; 10.08.2013
comment
И наоборот, если вы хотите, чтобы не множитель высоты тона в x и z, вы должны вместо этого просто указать xzLength = k - person Lake; 10.08.2013
comment
Извините, это была ошибка в моих утверждениях, которая заставила вас поверить, что x и z были затронуты только рысканием, отредактированным! - person Lake; 10.08.2013
comment
Когда вы говорите угол, вы имеете в виду тип 0–360 или это другое значение чисел? Я спрашиваю об этом, потому что я преобразовал свои значения поворота (рыскания) и вверх и вниз (тангаж), чтобы вернуть значения углов, но ваши методы только вроде работают. По мере того, как я панорамирую камеру больше, добавляя, в свою очередь, поворот (рыскание) и поворачивая камеру вправо, камера начинает двигаться влево и назад, а иногда и вправо. Я очень надеюсь, что это моя ошибка, но, возможно, вы найдете что-то не так. В любом случае спасибо за помощь! - person Brian_Entei; 10.08.2013
comment
Если вы используете тригонометрические функции, вы должны использовать углы в диапазоне 0,0 - 2 * Pi (Pi = 3,1429 ....). В моей логике тоже может быть ошибка, я еще раз проверю ^^ - person Lake; 10.08.2013
comment
ОК, круто. Я тоже посмотрю свой код, пока вы это сделаете! - person Brian_Entei; 10.08.2013
comment
О, одна вещь, если вы используете тригонометрические функции, право представлено углом 0,0, а затем против часовой стрелки. Если ваш угол рыскания 0,0 представляет юг, вы должны установить его -Pi / 2 перед выполнением cos / sin, иначе результат будет смещен. Кроме того, вы, кажется, идете по часовой стрелке, поэтому вам нужно умножить угол на -1, чтобы сделать его против часовой стрелки перед вычислением. - person Lake; 10.08.2013
comment
Подождите, так что 360 ° отличается от pi / 2 и тому подобного? Вероятно, это проблема, так как мне, так сказать, преобразовать градусы в градусы пи? - person Brian_Entei; 10.08.2013
comment
Вы должны использовать радианы. Просто используйте Math.toRadians (градусы). Например. Math.toRadians (360.0) - person Lake; 10.08.2013
comment
Похоже, это сработало! Большое спасибо за помощь! Все, что мне оставалось делать, это поправить поле, потому что оно почему-то было задом наперед. - person Brian_Entei; 10.08.2013
comment
Ой, подожди, теперь, когда я смотрю вниз, камера движется назад .. Я попробую исправить это сам, и еще раз спасибо за помощь. - person Brian_Entei; 10.08.2013
comment
Да, я думаю, вам нужно умножить все углы на -1,0, потому что вы представляете их противоположным образом, как это делают тригонометрические функции ^^ Всегда рад помочь;) - person Lake; 10.08.2013
comment
Хорошо, теперь я начинаю понимать, почему так много игр используют пробел для полета вверх и кнопку Shift для полета вниз ... Очень сложно заставить высоту тона взаимодействовать с осями x и z. сделайте так, как вы сказали, и пусть xzlength = k (расстояние). Спасибо! - person Brian_Entei; 10.08.2013
comment
Привет, @Lake, извини, что побеспокоил тебя еще раз, но как взять значение в радианах и повернуть его на 90 градусов влево или вправо? Я пытаюсь сделать так, чтобы нажатие влево заставляло камеру двигаться влево, а вправо - вправо. Вот что мне нужно, чтобы камера двигалась вперед, и это работает: double yaw = Math.toRadians ((this.getRender3D (). GetYaw () / 100) * 360); XZ [0] = - (xzLength * Math.cos (рыскание)); XZ [1] = - (xzLength * Math.sin (рыскание)); - person Brian_Entei; 11.08.2013
comment
Что ж, вы можете добавить или вычесть 90 перед вызовом toRadians, ИЛИ после этого вы можете добавить или вычесть Pi / 2 (3,1439 / 2). Надеюсь, это поможет ^^ - person Lake; 11.08.2013
comment
Да, это помогло! Спасибо, и исходя из того, что вы мне сказали, 90 градусов эквивалентны PI / 2? Если это так, я могу использовать это, чтобы облегчить себе жизнь во многих ситуациях. Спасибо еще раз! - person Brian_Entei; 11.08.2013