Вычисление угла между трехмерным объектом и точкой

У меня есть 3D-объект в DirectX11 с вектором положения и углом поворота для направления, на которое он смотрит (он вращается только вокруг оси Y).

D3DXVECTOR3 m_position;
float       m_angle;

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

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

D3DXVECTOR3 normDirection, normTarget;
D3DXVec3Normalize( &normDirection, ????);
D3DXVec3Normalize( &normTarget, &(m_position-target));

// I store the values in degrees because I prefer it
float angleToRotate = D3DXToDegree( acos( D3DXVec3Dot( &normDirection, &normTarget)));

Кто-нибудь знает, как я получаю вектор для текущего направления, на которое он смотрит, из значений, которые у меня есть, или мне нужно переписать его, чтобы я следил за вектором направления объекта?

РЕДАКТИРОВАТЬ: изменено "COS" на "ACOS".

РЕШЕНИЕ (при участии пользователя 2802841):

// assuming these are member variables
D3DXVECTOR3 m_position;
D3DXVECTOR3 m_rotation;
D3DXVECTOR3 m_direction;

// and these are local variables
D3DXVECTOR3 target;  // passed in as a parameter
D3DXVECTOR3 targetNorm;
D3DXVECTOR3 upVector;
float angleToRotate;

// find the amount to rotate by
D3DXVec3Normalize( &targetNorm, &(target-m_position));
angleToRotate = D3DXToDegree( acos( D3DXVec3Dot( &targetNorm, &m_direction)));

// calculate the up vector between the two vectors
D3DXVec3Cross( &upVector, &m_direction, &targetNorm);

// switch the angle to negative if the up vector is going down
if( upVector.y < 0)
    angleToRotate *= -1;

// add the rotation to the object's overall rotation
m_rotation.y += angleToRotate;

2 ответа

Решение

Если вы сохраняете ориентацию как угол, вы должны принять какую-либо ориентацию по умолчанию, когда угол равен 0, выразить эту ориентацию по умолчанию как вектор (например, (1.0, 0.0, 0.0), если вы принимаете направление x+ по умолчанию), затем поверните этот вектор на ваши угловые градусы (либо непосредственно с помощью sin/cos, либо с помощью матрицы вращения, созданной одной из функций D3DXMatrixRotation*), и результирующий вектор будет вашим текущим направлением.

РЕДАКТИРОВАТЬ:

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

D3DXVECTOR3 cross;
D3DXVec3Cross(&cross, &normDirection, &normTarget);
float dot;
D3DXVec3Dot(&dot, &cross, &normal);
if (dot < 0) {
    // angle is negative
} else {
    // angle is positive
}

куда normal скорее всего, это вектор (0, 1, 0) (потому что вы сказали, что ваши объекты вращаются вокруг оси Y).

Если, как вы говорите, 0 градусов == (0,0,1) вы можете использовать:

normDirection = (sin (угол), 0, cos(угол))

потому что вращение всегда вокруг оси у.

Вам придется изменить знак греха (угол) в зависимости от вашей системы (левша или правша).

Другие вопросы по тегам