5

私は最初の実際の OpenGL プロジェクトに取り組んでいます。3x3x3のルービックキューブです。ここに私がこれまでに持っているものの簡単なスクリーンショットへのリンクがあります(私のルービックキューブ)

キューブの回転は、マウスの右ボタンを押しながらマウスをドラッグすることで行います。これは、NeHe チュートリアル ( NeHe Arcball )のアークボールの例を使用して機能します。

6 つの実際のクワッドを介して 1 つの立方体を表すクラス singleCubes があり、その描画メソッドで使用できる表示リストに格納されています。クラス ComplexCube には 3x3x3 の singleCube の配列があり、完全なルービック キューブとやり取りするときにインターフェイスとして使用されます。

ここで、マウスの左ボタンを押したままドラッグすると、特定の各面を回転させたいと思います。ピッキングを使用して、ユーザーがクリックした単一の立方体の対応する面の ID を取得します。これも機能します。そこで、面上の 1 つの立方体の側面をクリックし、ドラッグの方向に応じて、影響を受ける立方体の回転とオフセット係数を設定します。(色を変更するだけでなく、実際に顔が回転するのを見ることも実装したい)

今私の問題は、マウスの右ドラッグでルービックキューブを任意の方向に回転させると、たとえば逆さまになることです。そのため、側面をクリックして面を右に回転させたい場合、立方体が逆さまになっているかどうかを追跡できないため、間違った方向に進んでしまいます。アークボール回転を使用しているため、これを決定するために使用できる x または y 回転角度がありません。

質問 1:上にリンクされているアークボールの例を使用しているときに、マウスのドラッグ情報 (1 つの面を回転させるとき) を変換するために、立方体が逆さまになっている場合、または後で情報を取得するにはどうすればよいですか?

// In render function
glPushMatrix();
{
    glMultMatrixf(Transform.M); // Rotation applied by arcball object
    complCube.draw();           // Draw all the cubes using display lists
}
glPopMatrix();

セットアップ: C++ と Microsoft Visual Studio 2008、GLEW、freeglut

4

2 に答える 2

4

gluUnProject を使用して、マウス座標を 3D 空間に変換し、ベクトル (2 点間の差) を取得できます。このベクトルを使用して、選択した面に「力」を適用できます。gluUnProject は射影行列を使用するため、カメラの向きを自動的に処理します。

基本的に、「力」ベクトルを取得したら、それを 3 つの軸 ((1,0,0)、(0,1,0)、(0,0,1)) に投影します。次に、大きさが最も大きいものを選択します。次に、下の図のように、この方向を回転軸に変換する必要があります (ペイント スキルが悪くてすみません)。

説明で使用するベクトルの例

これで、黒の「力」ベクトルと灰色の選択されたルービック面が得られました。回転軸を取得するには、選択した面の法線と「力」ベクトルの外積を取ります。これにより、赤い矢印が表示されます。そこから、キューブを正しい方向に回転させることができるはずです。

編集して質問に詳細に答える

私の説明から続けて、これがどのように役立つかの例を挙げます。まず、画面が 800x800 ピクセルで、ルービック キューブが常に中央にあると仮定します。ここで、コメントの図面に従って、左側のケースにいると仮定しましょう。

マウスをドラッグして、gluUnProject を使用してワールド座標に変換される 2 つの位置を取得します (数値は計算ではなく、ポイントを示すために選択されました)。

p1 : (600, 600) -> (1, -0.5, 0)
p2 : (630, 605) -> (1.3, -0.505, 0)

ここで差ベクトルを取得します: p2 - p1 = v = (0.3, -0.05, 0)。「3 つの軸に投影する」と言ったのは、主な動き (この場合は x 軸で 0.3) を抽出するためです (ルービック キューブは対角線に沿って回転できないため)。「投影」を行うには、x、y、z 軸を個別に取り、それらからベクトルを作成するだけで、次のようになります。

v1 = (0.3, 0, 0)
v2 = (0, -0.05, 0)
v3 = (0, 0, 0)

次に、大きさを取り、最小のベクトルを破棄します。したがって、ベクトル v1 = (0.3, 0, 0) が残ります。これは、ワールド空間での移動ベクトルです。次に、そのベクトルと、選択した面の法線ベクトル (この場合は (0, 0, 1)) との外積を取ります。これにより、(0, 1, 0) (正規化後) を指すベクトルが得られます (このステップでは、おそらく最大のコンポーネントのみ (0.02, 1.2, 0.8) を抽出する必要があります -> (0, 1, 0)そうしないと、カメラが主軸に沿って直接向いていないと、奇妙な回転が発生します)。そのベクトルを回転軸として使用し、回転量として 0.3 を使用できるようになりました (予想とは反対の方向に回転する場合は、- を入力してください)。

キューブが逆さまになっている場合、これはどのように役立ちますか? 同じように画面をクリックするとします。次のようになります。

p1 : (600, 600) -> (-1, 0.5, 0)
p2 : (630, 605) -> (-1.3, 0.505, 0)

ワールド座標の違いがわかりますか? 彼らは反転しています!したがって、差分ベクトルを取ると、p2 - p1 = v = (-0.3, 0.05, 0) となります。最大成分ベクトルを抽出すると、(-0.3, 0, 0) が得られます。外積をもう一度実行すると、回転軸が得られますが、今度は回転が反対方向になっています。これが目的です。

面の法線との外積のもう 1 つの理由は、(図面で) 上部の面を選択すると、x 軸または z 軸に沿った回転軸 (左側、またはこれは、上面に必要なものです。

于 2011-10-27T13:25:43.087 に答える
0

ほとんどの人がそうであるように、ジンバルロックと呼ばれる有名な問題に遭遇するでしょう。

参照: http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=208925

この問題は非常に詳細に文書化されているため、ここで詳細を説明する意味はあまりありません。私はあなたがそれについてたくさんの情報を見つけると確信しています.

于 2011-10-27T12:36:19.027 に答える