从两点和方向向量计算角度

时间:2011-02-02 21:16:47

标签: math vector

我在游戏中有两个向量。一个向量是玩家,一个向量是一个对象。我还有一个向量,指定玩家面对的方向。方向矢量没有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));

但似乎给我的结果不正确。有什么建议吗?

代码测试:

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 个答案:

答案 0 :(得分:9)

在计算角度增量时,你总是使用atan2,然后进行标准化。 原因是例如acos是域-1 ... 1的函数;如果输入绝对值(由于近似值)大于1,即使很明显在这种情况下你会喜欢0或PI的角度,函数也会失效。另外acos无法测量整个范围-PI..PI,您需要使用显式符号测试来查找正确的象限。

相反atan2只有奇点位于(0, 0)(当然,计算角度没有意义),其codomain是完整的圆-PI ... PI。

这是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

答案 1 :(得分:1)

在3D空间中,您还需要计算the axis

Vector3d axis = normalise(crossProduct(normalise(v1), normalise(v2)));