2

注意: 以下の質問を編集しました。これは、すぐ下のテキストよりも実際の問題に関連しています。必要に応じてスキップできますが、歴史的な理由からここに残しておきます。

これが正しいかどうかを確認するにはfloat、C の a はラジアンの値と同じですよね? つまり、360º = 6.28318531 ラジアンであり、OpenGL アプリで完全な回転が 0.0 から 6.28 になることに気付きました。これは正しく加算されているようです。私はそれが正しいことを確認したいだけです。

私は0.0 から 360.0 まで ( とfloat呼びましょう) を使用しています (度単位で読みやすく、常にキャストを避けることができます)。Web で見られるすべてのコードは、 として定義されている何らかのマクロを使用しています。最終的には次のようになります。anglePitchintfloatDEG2RAD()DEG2RAD 3.141593f / 180

anglePitch += direction * 1; // direction will be 1 or -1
refY = tan(anglePitch * DEG2RAD);

これは実際には 1 回転しますが、その 1 回転は と の場合になりますanglePitch = 180anglePitch * DEG2RAD = 3.14、1 回転は 360|6.28 である必要があります。マクロを次のいずれかに変更した場合:

#define DEG2RAD 3.141593f / 360
#define DEG2RAD 3.141593f / 2 / 180

期待どおりに動作し、anglePitch = 360.

ここで何が欠けていますか?角度をラジアン/フロートに適切に変換するには何を使用すればよいですか?

重要な編集 (本当の質問):
私は今、私がウェブ上のどこでも見ているコードを理解しています.私DEG2RADは数学が苦手です. だから私は私の質問を言い換えるつもりです:

これをコードに追加しました:

#define PI         3.141592654f
#define DEG2RAD(d) (d * PI / 180)

ここで、ピッチ/ヨーン角度を度単位で操作する場合、繰り返しになりますがfloats、常にキャスティングを避けるために、DEG2RADマクロを使用するだけで、度数の値が正しくラジアンに変換されます。これらの値は sin/cos/tan 関数に渡され、GLUT カメラで使用される適切な値を返します。

さて、本当の質問です。以前は本当に混乱していましたが、自分自身をうまく説明できませんでした:

angleYaw += direction * ROTATE_SPEED;
refX = sin(DEG2RAD(angleYaw));
refZ = -cos(DEG2RAD(angleYaw));

このコードは、LEFT/RIGHT キーを押すと実行され、それに応じてカメラが Y 軸で回転します。1 回転は 0° から 360° までです。

anglePitch += direction * ROTATE_SPEED;
refY = tan(DEG2RAD(anglePitch));

これは同様のコードで、UP/DOWN キーを押すと実行され、カメラは X 軸で回転します。しかし、この状況では、完全な回転は 0° から 180° まで変化し、それが私を本当に混乱させます。接線関数と関係があると確信していますが、頭がわかりません。

sin/cos を使用して (あくびのコードで行っているように) 同じ回転を実現する方法はありますか? 正しい方法、追加/修正できる最も単純なコード、および 0° から 360° までのフルピッチ回転を作成するためのより理にかなった方法は何ですか?

4

3 に答える 3

3

360°=2*円周率、円周率=3.141593…</p>

ラジアンは、半径1の円に沿った角度の弧長によって定義されます。円の周囲は2 * r * Piであるため、単位円を1回転すると、弧長は2 * Pi=6.28…</ p>

度単位の角度の測定は、6つの正三角形を整列させることにより、1回転にまたがるという事実に由来します。つまり、6つの三角形があり、それぞれがターンの6分の1を構成しているので、古いバビロニア人は円を1 /(6 * 6)= 1/36の断片に分割し、さらに洗練するために、これを10で分割しました。完全な円で360°になりました。ただし、この数は任意に選択されます。

したがって、2 * Pi / 360°がある場合、これはPi /180°=3.141593…/180°になります。これは、度からラジアンへの変換係数です。逆数、180°/ Pi = 180/3.141593…</p>

いったいなぜ古いOpenGL関数glRotateとGLUのgluPerspectiveがラジアンの代わりに度を使用したのか私には理解できません。数学的な観点からは、ラジアンだけが意味をなします。これはオイラー方程式によって最も美しく示されていると思います

e^(i*Pi) - 1 = 0

これで、すべての重要な数の数学が1つの方程式にまとめられました。これは角度と何の関係がありますか?上手:

e^(i*alpha) = cos(alpha) + i * sin(alpha), alpha is in radians!

修正された質問に関して編集:

フロートであるあなたの角度はすべて大丈夫です。なぜあなたは、私が理解できない整数であると思うでしょう。通常、PIを自分で定義する必要はありません。これは、math.hで事前定義されており、通常、Pi、2 * Pi、およびPi / 2の場合はM_PI、M_2PI、およびM_PI2と呼ばれます。また、マクロを変更する必要があります。マクロの記述方法によって、奇妙な効果が生じる可能性があります。

#define DEG2RAD(d) ( (d) * M_PI/180. )

GLUTにはカメラがまったくありません。GLUTは、私が使用しないことをお勧めするかなり馬鹿げたOpenGLフレームワークです。おそらくgluLookAtを参照します。

邪魔にならないこれらの障害は、そこで何をしているのか見てみましょう。三角関数は単位円で動作することを忘れないでください。角度0を右に向け、角度を反時計回りに増やします。次に、sin(a)は、右方向とcos(a)の量、および単位円上の角度aの点に到達するための前方の量として定義されます。これは、refXrefZが割り当てられているものです。

refYただし、そのように記述しても意味がありません。tan = sin / cosであるため、n * pi / 2(つまり、90°)に近づくと、+/-無限大に発散します。少なくともそれはあなたの円周率/180°の周期範囲を説明します、なぜならそれは日焼けの期間だからです。

私は最初、tanが方向ベクトルを正規化するために使用されたのではないかと考えていましたが、どちらも意味がありませんでした。係数は1./sqrt(sin²(Pitch)+1)でした 。私はダブルチェックしました。tanを使用すると正しいことが行われます。

EDIT2:あなたの問題がどこにあるのかわかりません:ピッチ角は-90°から+ 90°で、これは完全に理にかなっています。(地球の)地球儀を手に入れましょう:東西座標(経度)は-180°から+ 180°になり、南北座標(緯度)は-90°から+90°になります。考えてみてください。座標範囲が大きくなると、あいまいさが生じます。

私があなたに提供する唯一の良い提案は次のとおりです:いくつかの数学の教科書をつかんで、球座標の周りにあなたの心を曲げてください!そのように言ってすみません。あなたが持っているものが何であれ、完璧にうまく機能するものは何でも、あなたはただ特殊な幾何学を理解する必要があります。

ヨーとピッチという用語を使用しています。これらは通常、オイラー角で使用されます。残念ながら、最初は説得力のあるオイラー角が、後で深刻な問題を引き起こします(ジンバルロックなど)。それらをまったく使用しないでください。また、鉛筆/スティックなどを使用して、手で意図している回転を分解して、そのメカニズムを理解することもお勧めします。


ちなみに、非整数度もあります。http://maps.google.comにアクセスして、実際の動作を確認してください(場所を選択して、 http: //maps.google.comにリンクを表示させてください)

于 2011-03-06T13:37:27.993 に答える
3

'float' は int や double などの型です。ラジアンと度は測定単位であり、どちらも任意の精度で表すことができます。つまり、22.5 度を持たず、その値を float に保持できない理由はありません。

ラジアンでの完全な回転は 2*pi、約 6.283 ですが、度での完全な回転は 360 です。開始単位の完全な円を分割し、目的の単位の完全な円を掛けることで、それらの間で変換できます。

たとえば、90 度をラジアンに変換するには、まず度数を割ります。360 に対する 90 は 0.25 です (この値は「回転数」であることに注意してください)。その 0.25 に 6.283 を掛けると、1.571 ラジアンになります。

ファローアップ

ピッチ サイクルが本来の 2 倍の速さで表示されている理由は、Y コンポーネントを計算するために tan(pitch) を使用しているためです。あなたが持っているべきことは、Y 成分が sin(ピッチ) に依存するということです。つまり、変更してみてください

refY = tan(DEG2RAD(anglePitch));

refY = sin(DEG2RAD(anglePitch));

技術的な詳細: ルック マトリックスに入る数値はすべて -1 から +1 の範囲内である必要があります。refY に入力している値を調べる場合は、ピッチを -45 から + の範囲外で実行します。 45 度の場合、問題が発生します。tan() は +/-90 度で無限大になります。

また、値を int から float にキャストしても、度とラジアンの間で変換されるわけではないことに注意してください。キャストは、新しいストレージ タイプで最も近い同等の値を提供するだけです。たとえば、整数 22 を浮動小数点にキャストすると 22.0f になりますが、33.3333f を int 型にキャストすると 33 が残ります。組み込みプロセッサなどを使用することに制約されていない限り。これは、整数の増分が (約) 57.3 度の飛躍を表すラジアンの場合に特に重要です。

于 2011-03-06T13:22:30.090 に答える
1

refコンポーネントがルックアットベクトルとして使用されることを意図していると仮定すると、必要なのは

refY = sin(DEG2RAD(anglePitch)); 
XZfactor = cos(DEG2RAD(anglePitch));
refX = XZfactor*sin(DEG2RAD(angleYaw));
refZ = -XZfactor*cos(DEG2RAD(angleYaw));
于 2011-03-06T17:09:54.583 に答える