2012-06-10 10 views
1

Я немного ржавый.Как рассчитать азимут и высоту относительно направления камеры в 3D ...?

У меня есть вектор (camDirectionX, camDirectionY, camDirectionZ), который представляет собой мое направление камеры. У меня есть (camX, camY, camZ), который является моим положением камеры.

Тогда я объект, помещенный в (ObjectX, objectY, objectZ)

Как я могу вычислить, с точки зрения камеры, на высоте моего объекта Азимут & ??

ответ

4

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

Один из способов сделать это, чтобы построить полный ортонормированный базис камеры, затем придерживаться этого в матрице вращения и применять Это. «Ортонормированный базис» камеры - это фантастический способ сказать три вектора, которые указывают вперед, вверх и прямо от камеры. Все они должны находиться под углом 90 градусов друг к другу (это то, что означает бит орто), и все они должны быть длиной 1 (что означает нормальный бит).

Вы можете получить эти векторы с крошечным обманом: поперечное произведение двух векторов перпендикулярно (на 90 градусов) для обоих.

Чтобы получить обратный вектор, мы можем просто перекрещивать вектор направления камеры с (0, 1, 0) (вектор, направленный вверх). Вам нужно будет нормализовать вектор, который вы выходите из кросс-продукта.

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

Теперь у нас есть ортонормированный базис камеры. Если мы вставим эти векторы в строки матрицы 3x3, мы получим матрицу поворота, которая преобразует наше координатное пространство, чтобы камера указывала прямо на одну из осей (что зависит от того, в каком порядке вы вставляете векторы).

Теперь довольно легко вычислить азимут и возвышение объекта.

Чтобы получить азимут, просто сделайте atan2 по координатам x/z объекта.

Чтобы получить возвышение, проект объекта координат на х/г плоскости (только установить координату у 0), а затем сделать:

acos(dot(normalise(object coordinates), normalise(projected coordinates))) 

Это всегда будет давать положительный угол - вы, вероятно, хочу, чтобы свести на нет, если у объекта координаты меньше 0.

код для все это будет выглядеть примерно так:

fwd = vec3(camDirectionX, camDirectionY, camDirectionZ) 
cam = vec3(camX, camY, camZ) 
obj = vec3(objectX, objectY, objectZ) 

# if fwd is already normalised you can skip this 
fwd = normalise(fwd) 

# translate so the camera is at (0, 0, 0) 
obj -= cam 

# calculate the orthonormal basis of the camera 
right = normalise(cross(fwd, (0, 1, 0))) 
up = cross(right, fwd) 

# rotate so the camera is pointing straight down the z axis 
# (this is essentially a matrix multiplication) 
obj = vec3(dot(obj, right), dot(obj, up), dot(obj, fwd)) 

azimuth = atan2(obj.x, obj.z) 

proj = vec3(obj.x, 0, obj.z) 
elevation = acos(dot(normalise(obj), normalise(proj))) 
if obj.y < 0: 
    elevation = -elevation 

Одна вещи, чтобы следить за то, тх t перекрестное произведение вашего исходного вектора камеры с (0, 1, 0) вернет вектор нулевой длины, когда ваша камера обращена вверх или вниз.Чтобы полностью определить ориентацию камеры, я предположил, что она всегда «прямая», но это ничего не значит, когда она направлена ​​вверх или вниз - вам нужно другое правило.

+0

большое спасибо за ваш ответ. У меня есть некоторые трудности для его реализации. Я получил первую часть об упрощении путем перевода и поворота. Но после этого я потерялся. Действительно, «теперь у нас есть ортонормированный базис» означает, что я должен использовать его для ссылки объекта? Как мне это сделать? потому что x/z по азимуту вычисляет x, z в новый базовый, правый ...? – gluon

+0

@gluon Я обновил ответ с помощью некоторого псевдокода. Надеюсь, это сделает вещи более ясными. – dave

+0

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