Как получить перевод из матрицы просмотра

11

Как я могу получить положение камеры в мировом пространстве из матрицы вида? Единственные ответы, которые я видел на этот вопрос, предполагают, что перевод находится в последней строке / столбце, но это не сработает, поскольку матрица содержит [x (точка) вправо, y (точка) вверх, z (точка) взгляд]

nuit5
источник

Ответы:

10

Короткий ответ

Сначала инвертируйте матрицу вида. Затем получите перевод из последней строки / столбца.

Длинный ответ

Один из способов вывести содержимое матрицы вида - начать с рассмотрения камеры как любого другого объекта в мире и вычисления мировой матрицы для него:

RightX  RightY  RightZ  0
UpX     UpY     UpZ     0
LookX   LookY   LookZ   0
PosX    PosY    PosZ    1

Мировая матрица преобразует координаты из локального пространства в мировое пространство. Но в этом случае локальное пространство камеры и пространство обзора одинаковы, поэтому мы также можем сказать, что эта матрица преобразует координаты из пространства обзора в мировое пространство.

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

   RightX        UpX        LookX      0
   RightY        UpY        LookY      0
   RightZ        UpZ        LookZ      0
-(Pos*Right)  -(Pos*Up)  -(Pos*Look)  1      // * = dot product

И у вас такая матрица. Таким образом, чтобы вернуть положение камеры из нее, вам сначала нужно будет инвертировать ее, а затем вы можете получить перевод из последней строки (или столбца в зависимости от системы).

Дэвид Гувея
источник
1
Зачем сначала инвертировать матрицу? Если вы (надеюсь) знаете, находитесь ли вы в мажоре строк или мажорах столбцов, местоположение вектора перевода должно быть очевидным.
3Dave
7

Во-первых, я НАСТОЯТЕЛЬНО рекомендую просто хранить позицию как вектор отдельно, это значительно облегчит вычисления. В любом случае ...

[x (dot) right, y (dot) up, z (dot) look]не фактическая матрица представления. Сама матрица имеет вид:

1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1

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

Когда вы получаете матрицу (при условии, что это матрица 4x4), перевод всегда будет храниться либо в последней строке, либо в последнем столбце, в зависимости от того, является ли ваш класс матрицы упорядочением по главному ряду или по главному столбцу.

Вероятно, вас смущает тот факт, что вам нужны точечные продукты. Происходит упрощение математической математики, в этом вопросе переполнения стека есть более подробные ответы: /programming/349050/calculating-a-lookat-matrix

Решение можно найти здесь , вам нужно взять обратную матрицу и получить перевод этого:

Vector3 ViewTrans = Matrix.Invert(ViewMatrix).Translation;
Position = ViewTrans;
Роберт Роухани
источник
5

Другие ответы здесь объясняют, как получить положение камеры по матрице камеры.

Если часть матрицы камеры 3х3 имеет только вращение (без масштабирования или сдвига), как обычно, расчет можно оптимизировать, умножив перевод матрицы камеры на транспонирование поворота камеры. Положение камеры - это преобразованный вектор перевода, умноженный на -1. В GLSL это:

vec3 cameraPosition = -transpose(mat3(worldToCameraMatrix)) * worldToCameraMatrix[3].xyz;

или

vec3 cameraPosition = -worldToCameraMatrix[3].xyz * mat3(worldToCameraMatrix);

Это то, что я использовал в своих вершинных шейдерах, если я не хочу вычислять и передавать положение камеры как единое целое.

msell
источник