3

そこで、adroidでopenGLを学習するためのアプリの作成を開始しました。最初に、システムタイマーを使用して立方体を作成し、それを回転させる方法を説明する章を通過しました。次に、各面を1つの画像の異なるセグメントにマッピングしました。開発の目的で、各面には番号が付けられています。次に、ドラッグ機能を実装して、ユーザーがスワイプ方法に応じて立方体を上下または左右に回転できるようにしました。

まず、私の問題の背景をいくつか示します。

それぞれの面が開始した軸を中心に回転しているので、どちら側がカメラに面しているのかを追跡したいと思います。たとえば、次のように展開されたレイアウトを持つ立方体があるとします。

  2
  4
3 1 5
  6

ここで、1は画面に面する側、2は反対側(または背面)、4は上、5は右、6は下、3は左です。これは、3/5がx軸上にあり、4/であることを意味します。 y軸に6、z軸に1/2。

これが私の問題です:

立方体は、1つの軸を中心に回転するだけで正しく回転します(つまり、360になるまで左/右または上/下にのみ移動します)が、90 180または270に移動するだけの場合は、回転する軸が切り替わります。これは、立方体の各側面が開始した軸に固定されていることについて上記で述べたことが原因で発生します。

5が向くように右に一度回転すると、ユーザーの観点から見たz軸は立方体のx軸になります。これは、左/右に90度、次に上下に90度移動し始めると、さらに複雑になります。

一番上の数字から時計回りにリストされた数字の配列で顔を追跡しようとしましたが、どの数字から来たかによって、周囲の数字の新しい方向が変わりました。

例えば:

1から回転させた場合に画面に面するように、各番号を囲む番号をマップしました。

  4         2         4         1         4           
3 1 5     3 4 5     1 5 2     3 6 5     2 3 1     
  6         1         6         2         6      

2はワイルドカードです。これは、どの方向からでも取得できるため、1からの実際の初期番号レイアウトがないためです。

  6  
3 2 5
  4  

だから私の配列は

sidesOfFace1[] = {4,5,6,3}
sidesOfFace2[] = {6,5,4,3}
sidesOfFace3[] = {4,1,6,2}
sidesOfFace4[] = {2,5,1,3}
sidesOfFace5[] = {4,2,6,1}
sidesOfFace6[] = {1,5,2,3}

そして、MOVEは値を持つことができます

UP = 1  RIGHT = 2  DOWN = 3  LEFT = 4

次に、前の顔、現在の顔、最後の動きを追跡することで、新しい顔に移動する方向を次の顔に与えるものを選択するのに役立つオフセットを取得する式を見つけようとしました。大まかに私はこの解釈を思いついた:

prevface MOVE currFace
    1 -> UP(1) -> 4 -> RIGHT(2) -> 5

offset = opposite direction of MOVE - (sidesOfFace.indexOf(prevFace)+1)

So first I get
   1) DOWN - sidesOfFace4.indexOf(1)+1 => 3 - 3 = 0

   2) LEFT - sidesOfFace5.indexOf(4)+1 => 4 - 1 = 3

1)これは、4の周りの辺が、上から時計回りに、配列sidesOfFaceと同じ順序であることを示しています。したがって、ユーザーがもう一度スワイプすると、どちら側に行くのかがわかります。これは、立方体が回転すると視聴者にとって変化するため、立方体の正しい回転を設定できるようにするために不可欠です。

2)これは、オフセットがあることを示しています。配列を見ると、インデックス4は0であるはずですが、立方体は、上側がインデックス3、右が0、下が1、左になるように回転しています。は2です。

アプリの他の機能のためにどちら側が画面に面しているかを知る必要があるだけでなく、どちら側が画面に面しているかに応じて、立方体を正しい軸に沿って回転させる必要があるため、知る必要があります。xRotとyRotを追跡していますが、これらの回転は、立方体の軸ではなく、カメラ/ユーザーのビューに従って発生する必要があります。

たとえば、私はそれを見つけました:

axis for front face  up/down axis  right/left axis  (as seen by the camera)
    1   +z              +x             +y
    2   -z              -x             -y

    4   +y              +x             +z
    6   -y              -x             -z

    5   +x              +z             +y
    3   -x              -z             -y

これは、どちら側が画面に面しているかに応じて、上/下軸を中心にxRotationsを実行し、右/左軸を中心にyRotationsを実行する必要があることを意味します。

友人が、カメラに最も近い4つの頂点をチェックする可能性について何かを言いましたが、glRotate関数を使用しているため、どこからその情報を取得できるかわかりませんでした。ただし、立方体の回転を自動化できるように、前面のどちら側にどの数字があるかを知る必要があります。

あなたが実際に座ってこれをすべて読んだら、私は本当に感謝しています。あなたが私を正しい方向に導くことができれば。たぶん、この問題へのリンク、またはもっと良いのに既知の解決策は素晴らしいでしょう。私はこれに数日間苦労していて、これがすでに解決策のある問題であるかどうか疑問に思っていました。

皆さんありがとう、

アラン

4

2 に答える 2

1

正直なところ、あなたの投稿の最後の 3/4 を完全に読んでいませんでした。必要以上に複雑に見えます。

しかし、立方体のどちら側がカメラに最も近いかを検出したいだけの場合は、次のようにする必要があります。

回転していない立方体で、各方向のベクトルを作成します。

vec3 left(-1, 0, 0)
vec3 right (1, 0, 0)
vec3 up(0, 1, 0)
etc...

次に、キューブの現在のモデル ビュー マトリックスを取得します。立方体のモデルビューで法線を変換すると、結果のベクトルが目の空間に得られます。

vec3 leftInEyeSpace = modelView * left;
vec3 upInEyeSpace = modelView * up;
...

これは、目に対する各ベクトルの方向になります。

次に、立方体の中心からカメラを指すベクトルを定義します。

vec3 cubeToCamera= -normalize((modelView * vec4(0,0,0,1)).xyz);

次に、「cubeToCamera」ベクトルで各ベクトルのドット積を取得します。ベクトル間の角度が大きくなるにつれて内積が減少するため、大きさが最大の内積は、カメラに最も向いている内積になります。

float leftDot = dot(cubeToCamera, leftInEyeSpace)
float rightDot = dot(cubeToCamera, rightInEyeSpace)
...
于 2012-06-30T03:46:31.877 に答える
0

少し複雑ですが、このようなものは機能しますか? いくつかの方法を省略しましたが、私の一般的な考え方を理解していただければ幸いです。ブール変数を使用して、どちらの側がユーザーに面しているかを判断できるはずです。

private Boolean right, left, spin;
private Boolean up, down, upsideDown;
private Boolean rightSide, leftSide;
// All false by default.

public void swipe(int swipeDirection)
{
    // Swipe Direction - 0 = Right, 1 = Left, 2 = Up, 3 = Down
    switch (swipeDirection)
    {
    case 0:
        if (upsideDown)
        {
            swipeLeft();
        }
        else if (rightSide)
        {
            swipeDown();
        }
        else if (leftSide)
        {
            swipeUp();
        }
        else
        {
            swipeRight();
        }
        break;
    case 1:
        if (upsideDown)
        {
            swipeRight();
        }
        else if (rightSide)
        {
            swipeUp();
        }
        else if (leftSide)
        {
            swipeDown();
        }
        else
        {
            swipeLeft();
        }
        break;
    case 2:
        if (upsideDown)
        {
            swipeDown();
        }
        else if (rightSide)
        {
            swipeRight();
        }
        else if (leftSide)
        {
            swipeLeft();
        }
        else
        {
            swipeUp();
        }
        break;
    case 3:
        if (upsideDown)
        {
            swipeUp();
        }
        else if (rightSide)
        {
            swipeLeft();
        }
        else if (leftSide)
        {
            swipeRight();
        }
        else
        {
            swipeDown();
        }
        break;
    }
}

private void swipeRight()
{
    if (right)
    {
        right = false;
        spin = true;
    }
    else if (left)
    {
        left = false;
    }
    else if (spin)
    {
        spin = false;
        left = true;
    }
    else if (up)
    {
        up = false;
        if (rightSide)
        {
            rightSide = false;
            upsideDown = true;
        }
        else if (leftSide)
        {
            leftSide = false;
        }
        else
        {
            rightSide = true;
        }
    }
    else if (down)
    {
        down = false;
        if (leftSide)
        {
            leftSide = false;
            upsideDown = true;
        }
        else if (rightSide)
        {
            rightSide = false;
        }
        else
        {
            leftSide = true;
        }
    }
    else
    {
        right = true;
    }
}

private void swipeUp()
{
    if (down)
    {
        down = false;
    }
    else if (up)
    {
        upsideDown = !upsideDown;
    }
    else if (upsideDown)
    {
        upsideDown = false;
        up = true;
    }
}
于 2012-06-30T03:37:59.723 に答える