2017-06-11 22 views
0

デカルト座標系の点から球面座標で角度thetaとφを見つけようとします。opengl、球座標をデカルト座標から変換する

答えが見つかりました。正しくありません。しかし、私は何が起こっているのか理解できません。 私を助けてください。

はここに私のコードです:。。。_teye.get_posの

Vector4 g_eye(8.0f, 8.0f, 8.0f); 

Vector4 g_lookat(0.0f, 0.0f, 0.0f); 

Vector4 g_up(0.0f, -1.0f, 0.0f); 

struct spherical_sys 
{ 

    spherical_sys(Vector4& p) 
    { 
     _dirty = 1; 
     _pos = p; 
     _pos.w = 0.0f; 
     get_spherical(_pos, _theta, _phi, _r); 
    } 

    float getTheta() 
    { 
     return _theta; 
    } 

    float getPhi() 
    { 
     return _phi; 
    } 

    void setTheta(float t) 
    { 
     _theta = t; 
     _dirty = 1; 
    } 

    void setPhi(float t) 
    { 
     _phi = t; 
     _dirty = 1; 
    } 

    Vector4 get_pos() 
    { 
     if (_dirty) 
     { 
      float sin_phi, cos_phi; 
      float sin_theta, cos_theta; 
      FastMath::SinCos(_phi, sin_phi, cos_phi); 
      FastMath::SinCos(_theta, sin_theta, cos_theta); 

      _pos.w = 0.0f; 
      _pos[0] = _r* cos_phi * cos_theta; 
      _pos[1] = _r* sin_phi; 
      _pos[2] = _r* cos_phi * sin_theta; 
      _dirty = 0; 
     } 
     return _pos; 
    } 
private: 
    void get_spherical(Vector4& dir, float& theta, float& phi, float& r) 
    { 
     r = dir.Length(); 
     dir.Normalize(); 
     phi = FastMath::ACos(Vector3Dotf(dir, Vector4(0.0f, 1.0f, 0.0f, 0.0f))); 
     Vector4 v = Vector3CrossProduct(Vector4(0.0f, 1.0f, 0.0f, 0.0f), dir); 
     if (v.x < 0.0f) 
     { 
      phi *= -1; 
      phi = phi + MATH_PI * 0.5f; 
     } 
     else 
     { 
      phi = phi - MATH_PI * 0.5f; 
     } 
     theta = FastMath::ACos(Vector3Dotf(dir, Vector4(1.0f, 0.0f, 0.0f, 0.0f))); 
     v = Vector3CrossProduct(Vector4(1.0f, 0.0f, 0.0f, 0.0f), dir); 
     if (v.y < 0.0f) 
     { 
      theta *= -1; 
     } 
    } 
    float _phi; 
    float _theta; 
    float _r; 
    Vector4 _pos; 
    int _dirty; 
}; 
spherical_sys _teye(g_eye); 
spherical_sys _tup(g_up); 

答()のx、_teye.get_pos()Y、_teye.get_pos()zは6.531521、-7.998896、-9.238880ました。

明らかに、何かが間違っています。

答えて

2

カップルの問題のようです。私はあなたのコード体系には言及しません、ちょうど変換...

参照のため、ここではCartesian-Spherical conversionsの方程式です。

球形からデカルトへの変換が正しくありません。それは後ろ向きに見えるし、間違っている。

phi = FastMath::ACos(dir.y); 

別:ここでは、正しい方程式は(スワッピングY/Zについて下記の注意事項を参照してください)

 _pos[0] = _r* sin_theta * cos_phi; 
     _pos[1] = _r* sin_theta * sin_phi; 
     _pos[2] = _r* cos_theta; 

あなたの式の内積は無意味ですが、結果はベクトルのちょうどyコンポーネントでありますあなたはY軸とZ軸を入れ替えたようです。一貫性を保つ限り、これは問題ありません。このスワップでも、球面からデカルトへの変換はまだ間違っています。クラシックにとどまりましょう。

phi = FastMath::ACos(dir.z); 

次は、acos機能の範囲を修正するのに役立つために外積を使用しています。これはあなたがcompute the product by handになるまで「賢い」トリックであり、文字通りZ座標のみをチェックしていることがわかります。

cross((0,1,0), (x,y,z)) => (z,0,-x) 

次に、我々はシータ計算を検証します:

theta = FastMath::ACos(Vector3Dotf(dir, Vector4(1.0f, 0.0f, 0.0f, 0.0f))); 

ここでも、ドットprodcutは無用である、あなたはちょうどあなたが見ることができる簡体x

theta = FastMath::ACos(dir.x); 

を、グラブしていますコンポーネントが不足していて、誤った三角関数を使用していることを示します。 ArcTanとではなく、 ArcCosを使用してください。

theta = ATan2(dir.y, dir.x); 

また、クロス製品を使用して範囲を修正しているようです。しかし、手で製品を計算する:

cross ((1,0,0) , (x,y,z)) => (0,-z,y) 

だから、あなたは再び単純に、余分な計算の必要性を全くdir.z成分の符号をチェックされていません。


私のアドバイスは、古典的な式を使って最初に前後に変換することです。範囲を修正することについて心配する必要はありません。後でコードを動作させるときに範囲を固定することができます。

これが機能したら、範囲を修正してください。範囲が正しいとしたら、Z軸とY軸の入れ替えを心配してください。

ドットプロダクトまたはクロスプロダクトが何をしているかわからない場合は、手作業で作業してください。これらの関数の幾何学的意義を無視すると、計算が浪費され、一般的にコードが複雑になることがわかります。

幸運を祈る!

+0

dirベクトルが正規化されているように見えます。つまり、 'phi'と' theta'の計算で 'r'で割り切れることは間違っています。これを修正します... –

+0

私の元の考えでは、acos (dot(dir、unit_z))はphiを見つけることができ、theta acos(dot(dir、unit_x))と同じように2つの方向の間の角度を見つけることができます。しかし、おそらく何か間違っている。 –

+0

'phi'は' theta 'とは異なります。それは '[-pi、pi]'の範囲が異なります。ベクトルとX、Y平面の間の角度です。 「Theta」はX、Y平面の円の完全な方向、[0,2pi]です。乾杯! –

関連する問題