2011-02-02 22 views
4

私はゲームに2つのベクトルを持っています。 1つのベクトルはプレーヤー、1つのベクトルはオブジェクトです。私はまた、プレイヤーが向いている場合の方向を指定するベクトルを持っています。方向ベクトルにはzの部分はありません。それは起点のどこかに置かれた1の大きさを持つ点です。2点と方向ベクトルから角度を計算する

私は兵士が現在向いている方向とオブジェクトとの角度を計算したいので、いくつかの音声を正しくパンすることができます(ステレオのみ)。

下の図は私の問題を説明しています。私は2つの破線の間の角度を計算したいと思います。 1つの点線はプレーヤーとオブジェクトを接続し、もう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:数学は正しくありません。 1つの問題は、[0,2pi]の範囲の角度を必要とするとき、 'acos'は常に[0、pi]の範囲の角度を返します。あなたが情報を失うので、ドットプロダクトを取って、それから角度を計算することはできません。 あなたが必要とするものは[atl2]関数です。これは[-pi、pi]の範囲を持ち、[0,2pi]に十分接近しています - 単純な関数は絶対に必要な場合にこれを修正できますが、ほとんどの場合、大きな問題ではありません。 – dvitek

+0

atan2の第2引数として何を使用すればよいですか? – oggmonster

答えて

9

あなたは角度デルタを計算する際、常にatan2を使用して、正規化shoud。その理由は、例えばacosがドメイン-1 ... 1の関数であるからです。たとえ入力絶対値が(近似のために)1より大きくなっても、そのような場合には0またはPIの代わりにPIを使用することが明らかであっても、関数は失敗します。また、acosはフルレンジ-PI..PIを測定することができず、正しい四分円を見つけるために明示的に符号テストを使用する必要があります。

atan2では、特異点のみが(0, 0)(角度を計算するのは当然意味がありません)であり、そのコードドメインは完全な円-PI ... PIです。ここ

あなたは直交する方向、たとえばが必要一般的な3Dの向きの場合には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の場合、2つの参照方向が必要です。そうでなければ、ステレオ計算には役に立たない符号なしで角度を計算することができます。私は答えを広げます。 – 6502

+0

ええ、私はちょうど私の答えの下に表示されるコードでそれをテストしました。 しかし、vangleは-pi〜-2.35と2.35〜piの範囲にとどまります。ここで何がうまくいかないの?私はここにpiの完全な範囲を見なければならない? – oggmonster

1

、あなたもthe axisを計算する必要があります。

Vector3d axis = normalise(crossProduct(normalise(v1), normalise(v2))); 
関連する問題