Войти
ПрограммированиеФорумОбщее

Вращение мировых координат относительно камеры

Страницы: 1 2 Следующая »
#0

Всем привет.

Я только начинаю во всем этом разбираться, так что вопросы могут оказаться феерически тупыми )

Что дано:
Положение камеры в мировых координатах
Вектор направления камеры.
Стандартное управление для first person персонажа - WASD + мышка
Персонаж всегда смотрит и поворачивается в направлении камеры.

Что хочется:
Без обращения к инпутам (т.е. не отслеживая нажатия клавиш WASD) отслеживать перемещение персонажа исключительно по X вектору который является для персонажа forward вектором.
Т.е. нажав W мы будем задавать положительное смещение персонажа по X вектору, нажав S - отрицательное. Нажмем A или D будем смещать по Y, т.е. right вектору.
Т.е. вне зависимости от того какую кнопку мы нажали и куда смотрит камера, мы ходим знать на какую величину сместился персонаж в направлении своего X вектора.

В чем проблема: отслеживая перемещение по X все будет хорошо ровно до тех пор, пока мы не начнем поворачивать камеру влево или вправо, т.к. в случае некоего постоянного смещения при повороте в сторону смещение персонажа по данной оси будет снижаться, вплоть до полного 0 когда мы начнем двигаться перпендикулярно оси Y.
Проблема проиллюстрирована на картинке. Случай A и B то что мы имеем на текущий момент.

Мне видится решение проблемы в некоем повороте мировых координат которые мы получаем с нашей камеры. Поворачивая мировые координаты так, что бы X ось мира всегда была параллельна с X осью персонажа, вне зависимости от траектории движения и положения камеры, мы будем получать информацию о смещении персонажа вперед/назад.
Т.е. хочется как-то получить вариант C изображенный на картинке.
world | Вращение мировых координат относительно камеры

12 янв. 2019, 22:30

#1

Если это вся задача, то переусложняешь. Представь, что имеются:

1. Мировые координаты. Никаких других пока не требуется.

2. Игрок. У игрока есть позиция (вектор-точка P (position) в мировых координатах) и направление взгляда, заданное одним числом, уголом поворота (alpha) относительно какой-то оси. Пусть это будет ось X.

Из угла поворота можно получить единичный вектор направления «вперёд» F (forward):
Fx = cos(alpha); Fy = sin(alpha)

Куда бы ни был направлен взгляд игрока, если он сделает шаг вперёд на расстояние s, его новая позиция будет:
P' = P + F*s

К вектору позиции добавляется вектор направления, домноженный на длину шага.

Для шага вправо надо использовать вектор «вправо». В случае 2D вектор «вправо» (R) легко получить из вектора «вперёд»: Rx = Fy; Ry = -Fx.

PS
Исходил из классической, более часто используемой ориентации осей (X - вправо, Y - вверх) и положительного направления вращения ― по против часовой стрелки.

12 янв. 2019, 23:44 (Правка: 13 янв. 2019, 1:08)

#2

alexzzzz, пока что не выходит. Думаю где-то ошибаюсь. Угол мы должны считать в градусах или радианах?

13 янв. 2019, 0:58

#3

Надо смотреть, в чём принимают углы те функции sin и cos, которые вызываются. В подавляющем большинстве случаев радианы.

Если cos(90) не равен нулю, значит в радианах.

13 янв. 2019, 1:04 (Правка: 1:06)

#4

alexzzzz да будет тупость..)
Fx = cos(alpha) означает что мы берем косинус числа alpha, верно?

13 янв. 2019, 1:18

#5

Да, x-компонент вектора F равен косинусу угла alpha.

13 янв. 2019, 1:28 (Правка: 1:29)

#6

alexzzzz хм. Но если я беру косинус и синус альфы и делают их append в вектор, я фактически получаю абсолютно тоже самое что имел в самом начале - вектор направления камеры.

13 янв. 2019, 1:32

#7

Кажется, я прочитал не то что было написано, а что мне показалось. Ок.

Дано:
1. Вектор смещения игрока в мировых координатах.
2. Вектор направления взгляда игрока/камеры в мировых координатах.

Найти: тот же вектор смещения игрока, но в локальной системе координат игрока.

Сейчас правильно?

--
1. Прямая задача: перевести вектор [x,y] из локальной системы координат игрока в мировую систему:

Умножить вектор [x,y] на матрицу поворота:

| x' | = | cos -sin | * | x |
| y' |   | sin  cos |   | y |

В матрице стоят синусы и косинусы угла поворота. Они просто равны координатам вектора направления взгляда, если он единичный. Если эти координаты обозначить как [a, b], то будет

| x' | = | a -b | * | x |
| y' |   | b  a |   | y |
x' = a*x - b*y
y' = b*x + a*y

где [x', y'] - вектор в мировой системе координат
[x, y] - вектор в локальной системе координат игрока/камеры
[a, b] - единичный вектор направления игрока/камеры в мировой системе координат

2. Чтобы решить обратную задачу, надо заменить матрицу на обратную:

| x' | = |  a b | * | x |
| y' |   | -b a |   | y |
x' = a*x + b*y
y' = -b*x + a*y

где [x', y'] - вектор в локальной системе координат игрока/камеры
[x, y] - вектор в мировой системе координат
[a, b] - единичный вектор направления игрока/камеры в мировой системе координат

--
Как видно, прямая и обратная матрицы поворота в 2D не сильно-то и отличаются, только знаки синусов инвертируются. Но и сами эти знаки исходно зависят от того как направлены оси координат (у тебя они необычные) и какое направление вращения считается положительным.

В общем, какой-то из двух вариантов тебе подойдёт. Вставлять туда вектор смещения в мировой системе координат и получать вектор в локальной. Но какой из вариантов будет прямым, а какой обратным, не берусь предсказать.

13 янв. 2019, 3:43 (Правка: 22:15)

#8

alexzzzz Удивительно, но это почти работает. Теперь смещение камеры по forward вперед, абсолютно любом направлении дает положительное увеличение x' вне зависимости от направлении камеры, при смещении назад, значение, соответственно уменьшается.

Однако появилась проблема с резким изменением полученного значения x' при повороте камеры на месте.
При коллинеарности x и x' и повороте по часовой стрелке, x' резко уменьшается до достижения 45 градусов, после вновь начинает увеличиваться вплоть до достижения угла поворота 135 градусов, где величина изменений вновь снижается и дальше знак этих изменений вновь меняется на положительный.
Это справедливо для положения камеры с неким смещением относительно 0-х координат мира.
При положении камеры строго в 0-х координатах - данного эффекта нет.

13 янв. 2019, 5:56

#9

>Однако появилась проблема с резким изменением полученного значения x' при повороте камеры на месте.

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

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

13 янв. 2019, 15:54 (Правка: 17:27)

#10
Возможно, ты вставляешь в формулы не смещение игрока при движении, т.е. не разность позиций, а саму позицию.

Немного запутался.. Что имеется ввиду под разностью позиций?

14 янв. 2019, 0:58

#11
Т.е. вне зависимости от того какую кнопку мы нажали и куда смотрит камера, мы
ходим знать на какую величину сместился персонаж в направлении своего X вектора.

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

PS
Картинка B.

Начальная позиция игрока в мировых координатах [4, 2].
Конечная позиция в мировых координатах [5, 6].
Значит смещение в мировых координатах [1, 4].

Переводим это смещение в локальную систему координат игрока, должно получиться примерно что-то типа [5, 0]. Что говорит о том, что игрок двигался исключительно вперёд вдоль своей локальной оси X, держа клавишу W.

Что именно нарисовано на картинке С, не очень понятно. Не мировая система и не локальная, а вроде бы локальная, но с начальной позицией игрока в ней, взятой из мировой.

PPS
Если переводить из мировой системы координат в локальную не смещение, а саму позицию игрока, то в этом нет смысла. Где бы игрок ни находился и куда бы ни смотрел, его позиция в его локальной системе координат в любой момент времени равна [0, 0].

14 янв. 2019, 1:30 (Правка: 1:58)

#12
Персонаж каким-то образом куда-то сместился, значит у него была позиция P1, а стала P2. Вот (P2-P1) ― это его смещение, разность позиций. Это смещение надо подставлять в формулы, они переведут его из мировой системы координат в локальную.

Начальная позиция игрока в мировых координатах [4, 2].
Конечная позиция в мировых координатах [5, 6].
Значит смещение в мировых координатах [1, 4].

Переводим это смещение в локальную систему координат игрока, должно получиться примерно что-то типа [5, 0].

Но подождите.. Но проблема-то и состоит в том, что нам известно положение персонажа только в мировых координатах. Если бы имелось смещение в локальных координатах, то и проблемы бы не было )
Поэтому я и оперирую мировыми x, y персонажа подставляю в формулу именно их.
Т.е. стоит персонаж в х 100, у 200, значит:
x' = a*100 + b*200
y' = -b*100 + a*200

Разве не так?

14 янв. 2019, 6:55

#13

Игрок был в точке x=100, y=200 в мировых координатах. Нажимал какие-то клавиши и в результате переместился в x=103, y=204 в мировых координатах. Какие клавиши нажимал, не известно, но известен вектор направления взгляда игрока, тоже в мировых координатах.

Что хочется:
Без обращения к инпутам (т.е. не отслеживая нажатия клавиш WASD) отслеживать перемещение персонажа исключительно по X вектору который является для персонажа forward вектором.

Т.е. нажав W мы будем задавать положительное смещение персонажа по X вектору, нажав S - отрицательное. Нажмем A или D будем смещать по Y, т.е. right вектору.
Т.е. вне зависимости от того какую кнопку мы нажали и куда смотрит камера, мы ходим знать на какую величину сместился персонаж в направлении своего X вектора.

Т.е. надо узнать, куда сместился игрок относительно осей своей локальной системы координат, куда бы они ни были повёрнуты.

1. Знаем смещение игрока в мировых координатах: [103, 204] - [100, 200] = [3, 4]
2. Знаем куда была повёрнута камера игрока: [a, b]
3. Подставляем эти числа (x = 3, y = 4, a=…, b=…) в формулы, получаем то же самое смещение игрока, но в его локальной системе координат. (Если конечно направление взгляда не успело в процессе движения измениться.)

Если направление взгляда было [1, 0], т.е. совпадало с мировой осью X, то в результате должны получиться те же [3, 4], т.к. направление локальных осей совпадает с мировыми. Из [3, 4] понятно, что игрок держал клавиши W и D, причём клавишу D дольше. (Если считать, что +X ― это прямо, а +Y ― вправо, как на картинках).

Если направление взгляда было [0, 1], т.е. совпадало с мировой осью Y, то в результате должно получиться [4, -3]. Из [4, -3] понятно, что игрок держал клавиши W и A, причём клавишу W дольше.

Если направление взгляда было [0.6, 0.8], в результате должно получиться [5, 0], т.е. игрок шёл исключительно прямо по курсу, держа клавишу W, и вбок не смещался.

14 янв. 2019, 20:43 (Правка: 20:46)

#14

Картинка В.

1. Исходная позиция игрока в мировых координатах: [4, 2]
2. Конечная позиция игрока в мировых координатах: [5, 6]
3. Смещение игрока в мировых координатах: [5, 6] - [4, 2] = [1, 4]
4. Единичный вектор направления взгляда игрока в мировых координатах: [0.258819, 0.9659258]. Это я посчитал, взяв угол отклонения взгляда от оси X за 75°, а положительное направление вращения ― по часовой стрелке.

x=1, y=4, a=0.258819, b=0.9659258

x' = a*x + b*y
y' = -b*x + a*y
x' = 4.122522
y' = 0.06935048

Т.е. игрок сместился на 4.12 единиц прямо по курсу и ещё капельку вправо на 0.07 единицы.

14 янв. 2019, 21:05 (Правка: 21:06)

Страницы: 1 2 Следующая »
ПрограммированиеФорумОбщее