首页 文章

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

提问于
浏览
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));

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

代码测试:

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 回答

  • 1

    在计算角度增量时,你总是使用 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;
    

    在一般的三维方向的情况下,您需要 two 正交方向,例如鼻子指向的向量和右耳所在的向量 . 在这种情况下,公式稍微复杂一些,但如果你有点产品,则更简单:

    // 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

  • 9

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

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

相关问题