2011-02-02 5 views
4

게임에 두 개의 벡터가 있습니다. 하나의 벡터가 플레이어이고, 하나의 벡터가 객체입니다. 또한 플레이어가 직면 할 방향을 지정하는 벡터가 있습니다. 방향 벡터에는 z 부분이 없습니다. 원점 주변에 1의 크기를 갖는 점입니다.두 점과 방향 벡터로부터 각도를 계산하십시오.

군인이 현재 향하고있는 방향과 대상 사이의 각도를 계산하여 일부 오디오 (스테레오 전용)를 올바르게 팬 할 수 있습니다.

아래 그림은 내 문제를 설명합니다. 두 점선 사이의 각도를 계산하고 싶습니다. 한 점선은 플레이어와 객체를 연결하고, 다른 하나는 플레이어가있는 지점에서 플레이어가 향하고있는 방향을 나타내는 선입니다. 순간

Angle Problem

, 나는이 (플레이어, 객체와 방향이다 3 점, (X, Y, Z)와 모든 벡터 가정)하고있는 중이 야 :

Vector3d v1 = direction; 
Vector3d v2 = object - player; 
v1.normalise(); 
v2.normalise(); 
float angle = acos(dotProduct(v1, v2)); 

을하지만 줄 것으로 보인다 나 부정확 한 결과. 어떤 충고? 코드의

테스트 : 3D 공간에서

Vector3d soldier = Vector3d(1.f, 1.f, 0.f); 
Vector3d object = Vector3d(1.f, -1.f, 0.f); 
Vector3d dir = Vector3d(1.f, 0.f, 0.f); 

Vector3d v1 = dir; 
Vector3d v2 = object - soldier; 

long steps = 360; 
for (long step = 0; step < steps; step++) { 
    float rad = (float)step * (M_PI/180.f); 
    v1.x = cosf(rad); 
    v1.y = sinf(rad); 
    v1.normalise(); 

    float dx = dotProduct(v2, v1); 
    float dy = dotProduct(v2, soldier); 
    float vangle = atan2(dx, dy); 
} 
+2

귀하의 수학 소리를, 당신은 '잘못된 결과'가 무엇을 의미하는지 명확하게. 그것은 당신이 기대하는 것과 약간의 상쇄입니까? 우리가 테스트 한 번호를 알려주십시오. –

+2

@Ron Warholic, oggmonster : 수학이 정확하지 않습니다. 한 가지 문제는 [acos]는 [0,2pi] 범위의 각도를 원할 때 [0, pi] 범위의 각도를 항상 반환한다는 것입니다. 당신은 정보를 잃어 버리기 때문에 점 제품을 가져 와서 그 각도를 계산할 수는 없습니다. 당신이 필요로하는 것은'-pi, pi]의 범위를 갖는'atan2' 함수입니다. [0,2pi]에 충분히 가깝습니다 - 간단한 함수는 절대적으로 필요하다면 이것을 고칠 수 있지만 음의 각도는 대부분의 경우 큰 문제는 아닙니다. – dvitek

+0

atan2의 두 번째 인수로 무엇을 사용해야합니까? – oggmonster

답변

9

당신은 항상 정상화 후 각 델타를 계산할 때 atan2을 사용하고 갈까요. 그 이유는 예를 들어 acos이 도메인 -1 ... 1; 입력 된 절대 값 (근사값 때문에)이 1보다 커지면 함수가 실패 할 것입니다. 그런 경우에는 0이나 PI 대신에 각도를 좋아할 것입니다. 또한 acos은 전체 범위 -PI..PI를 측정 할 수 없으며 올바른 사분면을 찾기 위해 명시 적으로 부호 테스트를 사용해야합니다.

대신 atan2만의 특이점은 (0, 0)입니다 (물론 각도를 계산하는 것은 의미가 없습니다). 그 코모 메인은 완전한 원 -PI ... PI입니다. 여기

개의 직교 방향, 예를 들어 필요 일반적인 3 차원 방향의 경우는 C++

// Absolute angle 1 
double a1 = atan2(object.y - player.y, object.x - player.x); 

// Absolute angle 2 
double a2 = atan2(direction.y, direction.x); 

// Relative angle 
double rel_angle = a1 - a2; 

// Normalize to -PI .. +PI 
rel_angle -= floor((rel_angle + PI)/(2*PI)) * (2*PI) - PI; 

예이다 코가 가리키는 곳의 벡터와 오른쪽 귀가있는 곳의 벡터. 공식은 단지 약간 더 복잡하다이 경우 하지만, 간단한 당신이 편리 내적있는 경우 :

// I'm assuming that '*' is defined as the dot product 
// between two vectors: x1*x2 + y1*y2 + z1*z2 
double dx = (object - player) * nose_direction; 
double dy = (object - player) * right_ear_direction; 
double angle = atan2(dx, dy); // Already in -PI ... PI range 

enter image description here

+0

@Ron Warholic : 3d의 경우 두 가지 참조 방향이 필요합니다. 그렇지 않으면 스테레오 계산에 쓸모없는 기호없이 각도를 계산할 수 있습니다. 나는 대답을 연장 할 것이다. – 6502

+0

흠, 그냥 내 대답 아래에 보이는 코드로 테스트했습니다. 그러나 vangle은 -pi에서 -2.35 범위에 있고 2.35에서 pi 사이에 있습니다. 여기서 뭐가 잘못 됐니? 나는 여기에 pi의 전체 범위를보아야한다. – oggmonster

1

은 또한 the axis을 계산해야합니다

Vector3d axis = normalise(crossProduct(normalise(v1), normalise(v2))); 
관련 문제