2012-03-20 2 views
1

Я пытаюсь вычислить угол между двумя векторами, чтобы я мог вращать символ в направлении объекта в трехмерном пространстве. У меня есть два вектора (характер & объект), loc_look и modelPos соответственно. Для простоты я просто пытаюсь вращаться вдоль оси ... рыскания. loc_look = D3DXVECTOR3 (0, 0, 1), modelPos = D3DXVECTOR3 (0, 0, 15);Вычисление угла между двумя векторами с использованием точечного продукта

Я написал этот код, который кажется правильным. Моя проблема возникает, по-видимому, потому что поворот, который я применяю к вектору взгляда персонажа (loc_look), превышает значение позиции объекта (modelPos). Вот мой код:

BOOL CEntity::TARGET() 
{ 
    if(graphics.m_model->m_enemy) 
    { 
     D3DXVECTOR3 modelPos = graphics.m_model->position; 
     D3DXVec3Normalize(&modelPos, &modelPos); 

     //D3DXVec3Normalize(&loc_look, &loc_look); 
     float dot = D3DXVec3Dot(&loc_look, &modelPos); 
     float yaw = acos(dot); 
     BOOL neg = (loc_look.x > modelPos.x) ? true : false; 
     switch (neg) 
     { 
     case false: 
      Yaw(yaw); 
      return true; 
     case true: 
      Yaw(-yaw); 
      return true; 
     }   
    } 
    else 
     return false; 
} 

поворачивать матрицу ориентации персонажа со следующим кодом:

void CEntity::CalculateOrientationMatrix(D3DXMATRIX *orientationMatrix) 

{  

D3DXMatrixRotationAxis(&rotY, &loc_up, loc_yaw); 

D3DXVec3TransformCoord(&loc_look, &loc_look, &rotY); 

D3DXVec3TransformCoord(&loc_right, &loc_right, &rotY); 


D3DXMatrixRotationAxis(&rotX, &loc_right, loc_pitch); 

D3DXVec3TransformCoord(&loc_look, &loc_look, &rotX); 

D3DXVec3TransformCoord(&loc_up, &loc_up, &rotX); 


D3DXMatrixRotationAxis(&rotZ, &loc_look, loc_roll);  

D3DXVec3TransformCoord(&loc_up, &loc_up, &rotZ); 

D3DXVec3TransformCoord(&loc_right, &loc_right, &rotZ); 

*orientationMatrix *= rotX * rotY * rotZ; 


orientationMatrix->_41 = loc_position.x; 

orientationMatrix->_42 = loc_position.y; 

orientationMatrix->_43 = loc_position.z; 


//D3DXVec3Normalize(&loc_look, &loc_look); 

SetYawPitchRoll(0,0,0); // Reset Yaw, Pitch, & Roll Amounts 

} 

Также к сведению, что увеличивается modelPos.x на 0,1 каждую итерацию, так что персонаж столкнется объект когда он перемещается вдоль оси x ... Теперь, когда я запускаю программу, на первой итерации все нормально (я еще не повернул символ). На второй итерации значение loc_look.x больше, чем значение параметра modelPos.x (я слишком сильно повернул символ, используя угол, указанный при вычислениях точек в функции TARGET). Поэтому на второй итерации мой код будет вращать символ слева, чтобы отрегулировать разность значений векторов x ...

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

+0

(0,0,1) и (0,0,15) являются параллельными, не так ли? –

+0

да ... хорошая точка, но объект перемещается вправо на каждую итерацию. значение look.x превышает значение modelPos.x на второй итерации, а затем соответственно корректирует (поворачивается влево). Результатом является дрожащий аффект (персонаж дрожит справа, а затем несколько раз). –

+0

Я пробовал преобразовывать градусы в радианы до «рыскания» (Yaw ((D3DXToRadian (yaw)), что предотвращает дрожание, но только потому, что угловое изображение значительно уменьшено ... вектор взгляда никогда не равен вектору modePos ... –

ответ

4

Точечный продукт является косинусом угла между двумя векторами, только если они являются единичными векторами. Пожалуйста, смотрите это:

http://en.wikipedia.org/wiki/Dot_product#Geometric_interpretation

Я вижу, у вас есть некоторые закомментирована строку:

//D3DXVec3Normalize(&loc_look, &loc_look); 

Но вы должны нормализовать оба вектора.

Подумайте об этом. Если векторы все масштабируются постоянным фактором, точечный продукт становится больше, не так ли? И поэтому значение, идущее в arccos, больше. Но угол один и тот же, так что это явно неправильно.

+0

должна ли сумма каждого значения вектора равным 1 после нормализации? Mine do not ... –

+0

Кроме того, в отношении вашего примера ** oc_look = D3DXVECTOR3 (0, 0, 1), modelPos = D3DXVECTOR3 (0, 0, 15) ** Говорят, что персонаж смотрит прямо вверх по оси Z? и модель также прямо над головой? В этом случае угол равен нулю. Если вы заинтересованы только в рыскании, кажется, что лучшим примером может быть что-то вроде взгляда на <1, -1, 0>, а объект находится на <3, 4, 0>. Является ли ваша ось «вверх» осью Z? – Kaz

+0

Нет! ** длина ** единичного вектора равна 1, а не сумме компонентов. Если вы берете точечный продукт единичного вектора с самим собой, это должно быть 1. То есть x * x + y * y + z * z = 1. (И поэтому sqrt (x * x + y * y + z * z) = 1). – Kaz

0

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