在android opengl es中检测面向摄像头的立方体的一侧

时间:2012-06-30 00:52:12

标签: android opengl-es cubes

所以我开始创建一个app来学习adroid上的openGL。首先,我通过一章解释了如何使用系统计时器构建一个立方体并使其旋转。然后我将每一面映射到一个图像的不同部分。出于开发目的,每一面都有一个数字纹理。然后,我实现了拖动功能,允许用户根据滑动方式上/下或左/右旋转立方体。

首先是我的问题背景:

我想跟踪哪一面朝向相机,因为每张面都在它开始的轴上旋转。例如,给定具有展开布局的立方体如下。

  2
  4
3 1 5
  6

其中1是面向屏幕的一侧,2是相对的(或背面),4是向上,5是向右,6是向下,3是向左。这意味着3/5在x轴上,y轴为4/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,但是立方体已经旋转,使得UP侧现在在索引3,RIGHT是0,DOWN是1 ,LEFT是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功能,我不知道从哪里可以得到这些信息。但是我仍然需要知道前面哪一侧有哪些数字,所以我可以自动旋转立方体。

如果你真的坐下来阅读这一切,我真的很感激,如果你能引导我朝着正确的方向前进。也许一个链接,或更好的解决这个问题的解决方案将是惊人的。我几天来一直在努力解决这个问题,我只是想知道这是否已经是一个有解决方案的问题。

全心全意,

艾伦

2 个答案:

答案 0 :(得分: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)
...

答案 1 :(得分: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;
    }
}