2

私はしばらくの間、宇宙シミュレーションに取り組んできました。最初は、ソフトウェア ラスタライザーを備えた独自の 3D エンジンを使用していました。

しかし、テクスチャを実装する時期が来たときにあきらめました。しばらくしてから再開し、代わりに Opengl (SDL) を使用して 3d モデルをレンダリングしています。

しかし今、私は別のレンガの壁にぶつかっています。

適切な回転の仕方がわかりません。宇宙シミュレータなので、fligsim と同様のコントロールが必要です

使用して

glRotatef(angleX, 1.0f, 0.0f, 0.0f);
glRotatef(angleY, 0.0f, 1.0f, 0.0f);
glRotatef(angleZ, 0.0f, 0.0f, 1.0f);

モデル (宇宙船) を最初に左に 90 度回転させてから「上」に回転させると、
正しく動作しません。代わりに転がります。

ここに私の問題を説明する画像があります。

画像リンク

これに対抗するためにいくつかのトリックを試しましたが、どういうわけか何かが足りないと感じています. シミュレーター スタイルの回転の例を見つけるのがほとんど不可能であることも役に立ちません。

そのため、例、リンク、および 3D モデル (宇宙船、飛行機など) を回転させる理論を探しています。

向きに 3 つのベクトル (左、上、前) を使用する必要があるのは、スラスターからの加速度や、回転 (向き?) とともに変化するものからの加速度などを計算する必要があるためです。ロケットエンジンのような方向。

私は数学が苦手で、解決策を視覚化しようとすると頭痛がするだけです

4

6 に答える 6

4

状況を完全に理解しているとは言えませんが、ジンバルロックについて説明しているようです。回転を表すためにクォータニオンを使用することを検討することをお勧めします。

于 2009-08-01T23:44:08.147 に答える
4

これを正しく行うことは確かに困難な場合があります。私が直面している問題は、「船」がすでにどのように方向付けられているかに関係なく、回転に同じ変換行列を使用していることです。ただし、船が前を向いているときにどのように回転するかに基づいて船を回転させるのではなく、現在の向きに基づいて回転させる必要があります。そのためには、船を変形させるのと同じ方法で、制御されたターンマトリックスを変換する必要があります。

たとえば、3つの行列があり、それぞれが実行したいターンの種類を表しているとします。

float theta = 10.0*(pi/180.0)

matrix<float> roll = [[ cos(theta), sin(theta), 0]
                       [ -sin(theta), cos(theta), 0]
                       [ 0, 0, 1]

matrix<float> pitch = [[ cos(theta), 0, sin(theta)]
                      [ 0, 1, 0]
                      [ -sin(theta), 0, cos(theta)]

matrix<float> yaw = [[1, 0, 0]
                     [0, cos(theta), sin(theta)]
                     [0, -sin(theta), cos(theta)]]

matrix<float> orientation = [[1, 0, 0]
                            [0, 1, 0]
                            [0, 0, 1]]

それぞれ、3つの飛行姿勢軸のそれぞれを横切る10度の回転を表します。また、船の向きのマトリックスがあります。最初はまっすぐ前方にあります。船の頂点をその方向マトリックスで変換して表示します。

次に、ターン後にオリエンテーションを取得するには、少し賢くする必要があります。最初に姿勢制御マトリックスをプレーヤーの座標に変換し、それをオリエンテーションに適用して、新しいオリエンテーションを取得します。

function do_roll(float amount):
    matrix<float> local_roll = amount * (roll * orientation)
    orientation = orientation * local_roll

function do_pitch(float amount):
    matrix<float> local_pitch = amount * (pitch * orientation)
    orientation = orientation * pitch_roll

function do_yaw(float amount):
    matrix<float> local_yaw = amount * (yaw * orientation)
    orientation = orientation * local_yaw

そのため、何らかの方法で回転するたびに、それらの関数の1つを呼び出すだけです。

于 2009-08-01T23:55:45.643 に答える
2

ここで使用したいのはクォータニオンです。彼らはあなたが経験している奇妙な行動を排除します。それらを同様の機能を持つステロイドのマトリックスと考えてください。特定の回転軸ベクトル上に回転行列を作成できるOpenGL機能を使用することで、(上記のコードで)自分よりも優れた行列を使用できますが、クォータニオンは格納します将来の変更のためのローテーション。たとえば、アイデンティティクォータニオンから始めて、特定の軸ベクトル上で回転させます。次に、クォータニオンはオブジェクトのワールドマトリックスに変換されますが、クォータニオンはオブジェクト内に格納されたままになります。次回、回転を実行する必要がある場合は、X、Y、Z軸の回転角度などを追跡するのではなく、そのクォータニオンをさらに変更します。

私の経験はdirectx内にあります(申し訳ありませんが、ここではOpenGLの経験はありません)が、部屋の周りで跳ね返り、床や壁などに遭遇したときに回転するビーチボールを回転させようとしたときに、問題に遭遇したことがあります。

Googleには「OpenGLQuaternion」に関する多数のオプションがありますが、これは特に、優れた情報源のようです。

http://gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation

ご想像のとおり、Quaternionsは環境内でカメラを処理するのに最適です。これが素晴らしいチュートリアルです:

http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=Quaternion_Camera_Class

于 2009-08-01T23:42:33.673 に答える
2

回転を制御する方法をより深く理解できるように、3D 数学を学習する必要があります。理論を知らないと、正しくコピーして貼り付けることさえ難しい場合があります。具体的には、3D Math Primer ( Amazon ) などのテキストや、http: //gamemath.comなどの関連サイトが、プロジェクト (および将来のすべてのプロジェクト) に大いに役立ちます。

あなたが今数学が好きではないかもしれないことは理解していますが、関連する算術を学ぶことがあなたの問題に対する最善の解決策になるでしょう。

于 2009-08-02T05:57:09.950 に答える
1

クォータニオンが役立つ場合がありますが、より簡単な解決策は、厳密な回転順序を観察することです。yを中心に回転し、次にxを中心に回転しているように聞こえます。常に最初にx、次にy、次にzを回転させる必要があります。その順序には特に特別なことはありません。そのようにすると、回転は期待どおりに機能する傾向があります。

編集:少し明確にするために、ゲーム内で時間の経過とともに累積的に回転することもすべきではありません。各フレームは、モデルを同一の位置から開始し、次にx、y、zの順に回転してそのフレームの新しい位置に配置する必要があります。

于 2009-08-01T23:57:39.273 に答える
1

一般的なローテーションは難しいです。物理学者は、それらを記述するために、いわゆるオイラー角のセットを使用する傾向があります。この方法では、一般的な回転は、固定された連続した 3 つの軸の周りに取られる 3 つの角度によって記述されます。しかし、3 つの軸は、元のフレームの X、Y、および Z 軸ではありません。多くの場合、元のフレームの Z 軸、Y 軸、Z 軸 (はい、これは完全に一般的なものです)、または元のフレームの 2 つの軸の後に中間フレームの軸が続きます。多くの選択肢が利用可能であり、最後まで同じ慣習に従っていることを確認するのは非常に面倒です。

于 2009-08-02T04:50:57.637 に答える