Google VR如何使用白日梦控制器执行选择

时间:2018-01-10 05:47:02

标签: android opengl-es-2.0 daydream

以下是我的案例

  • 我有一个left=0,right=1824,top=0,bottom=989的长方形,宽高比1.84f,统一z axis = -3f
  • 在那个矩形中,我有一个宽度和高度分别为344和182的小矩形。我将这些小矩形排列在3行和3列中,类似于网格图库。
  • 我在正交投影中做了一些修改而没有改变z轴,这样新的矩形将在-1,84 to 1.84 in x axis1 to -1 in y axis范围内,所有小矩形都在这些范围内
  • 然后在VR上渲染这些矩形,我只需应用

    view = perspective ( z near 0.1f, far 100 f) * eye.getEyeVew model = Orthographic transformation to come in range ( -1.84f to 1.84 f : X , 1 to 1f :Y ) modelview = view * model

  • 为了模拟控制器,我使用了一个带有( centerX=0, centerY=0, radius =0.04f, zaxis = -3f)

  • 的简单圈子
  • 使用控制器旋转矩阵(https://developers.google.com/vr/reference/android/com/google/vr/sdk/controller/Orientation.html#toRotationMatrix(float[])

    转换到圆后应用

    view = perspective ( z near 0.1f, far 100 f) * eye.getEyeVew controllerMatrix = controller.toRotationMatrix modelView = view * controllerMatrix

我的假设是,

  • 因为我正在绘制具有均匀Z值的3D平面,所以我可以将它们视为2D平面以供选择。
  • 我假设圆形2D坐标(左,上,右,下)可用于检查平面2D坐标(左,上,右,下)并查看圆是否落入平面。
  • 但由于视角和eye.getEyeView转换,圆和平面的z轴都发生了变化。

所以,我的问题是为了这个目的,我应该去RayCasting还是有一个简单的解决方案,用VR控制器选择小矩形。 我正在使用GVR控制器( Google VR version 1.80.0 )并使用Android进行应用开发。

谢谢

2 个答案:

答案 0 :(得分:1)

Google VR SDK附带了一些有用的示例项目,演示了如何实现这一目标。如果您检查Treasure Hunt project,则TreasureHuntActivity类的方法为isLookingAtObject()

private boolean isLookingAtObject() {
    // Convert object space to camera space. Use the headView from onNewFrame.
    Matrix.multiplyMM(modelView, 0, headView, 0, modelCube, 0);
    Matrix.multiplyMV(tempPosition, 0, modelView, 0, POS_MATRIX_MULTIPLY_VEC, 0);

    float pitch = (float) Math.atan2(tempPosition[1], -tempPosition[2]);
    float yaw = (float) Math.atan2(tempPosition[0], -tempPosition[2]);

    return Math.abs(pitch) < PITCH_LIMIT && Math.abs(yaw) < YAW_LIMIT;
}

这将计算摄像机视线方向上的矢量与modelCube矩阵之间的角度。 modelCube矩阵是一个4x4矩阵,用于定义3D场景中对象中心点的比例,旋转和平移。在您的情况下,这将是3D空间中矩形的中心点。

您还必须计算定义摄像机指向方向的矢量与矩形相交的角度。如下图所示:

enter image description here

此处原点是您的相机位置,C点是3D空间中渲染的矩形的质心,矢量 OC 是您的相机直接聚焦时指向的方向矢量矩形的中心。 Ꝋ是X-Z平面中从X轴到C点的角度。点P1-4是3D空间中矩形的顶点。

音高ɸ在下图中定义:

enter image description here

此处ɸ是从中心点 C 到新轴 e 的角度。

PITCH_LIMIT是两个向量之间的Y- e 平面中的角度。从摄像机位置到对象边界框底边的矢量,以及从摄像机位置到对象边界框上边缘的矢量。在这种情况下,它可以计算为 OP3 OP4 之间的角度或 OP2 OP1 之间的角度。这在以下2D横截面中描述:

enter image description here

假设相机正在直视矩形,此限制定义了在相机中心不再直接指向矩形之前相机必须向上倾斜的程度。

YAW_LIMIT是两个矢量之间XZ平面中的角度,从摄像机位置到对象边界框最左边缘的矢量,以及从摄像机位置到右边的矢量对象边界框的最边缘。在这种情况下,它可以计算为 OP1 OP4 之间的角度或 OP2 OP3 之间的角度。这在以下2D横截面中描述:

enter image description here

同样,此限制定义了在相机中心不再直接指向矩形之前,相机可以向左或向右旋转的程度。

请注意,如果您距离对象较远,YAW_LIMITPITCH_LIMIT值会变小,如果距离较近,则值会变大。您必须根据当前摄像机位置和对象的边缘顶点计算要查看的对象的这些限制。从对象空间到相机空间的坐标转换是在isLookingAtObject()方法中处理的。

答案 1 :(得分:1)

首先,需要查看sparkplug提供的上述详细说明,其中包含与该问题相关的所有概念。而且我欠sparkplug提供这样一个与这个问题有关的伟大概念,没有谁,就找不到答案。

接下来,如果您无法理解atan2的内容,请按照此link进行操作。从三角公式tan(angle) = perpendicular/base开始,如果您有perpendicularbaseatan2,则会给出角度。基本上atan2将给出两点之间的角度。在我们的例子中,点1是原点0,0,0,而其他点是矩形的中心点或矩形的任何顶点。因此,矩形中的原点和点之间的差异将仅仅是点值,即x-0 = x, y-0 = y, z-0 = z。此外,在我们的例子中,我们参考z axis计算角度,即base

如果您在理解YAWPITCH的概念时遇到一些困难,我将对头部运动进行类比。让你的头伸直,向前看,然后向左移动你的头,然后向右移动你的头。这是YAW,即你的头部在左右方向上移动的角度。再次抬头,向前看,然后上下移动头部。这是PITCH,即你的头部向上和向下移动的角度。

对头部运动进行类比,颈部和头部之间的点是枢轴点。向上和向下移动您的头部,您的眼睛将朝PITCH方向扫描。同样,采用相同的枢轴点,将头部从左向右移动,您的眼睛将在YAW方向扫描。

在这个解决方案中,我们需要计算我们的头部移动的角度,以便在宽度和高度上扫描整个矩形。

接下来,采取上述类比并研究daydream controller sample。您需要研究它给出的YAWPITCH值。为了简化研究,将控制器平放在桌子上,触摸板远离您。然后按照您在表格中旋转瓶子的方式稍微向左和向右移动控制器。您会注意到YAW值的范围。然后轻轻拿起控制器,然后上下移动。这将给出控制器的PITCH值范围。为简单起见,我们的控制器将被设置为原点,或者为了使问题更简单,您可以将控制器视为位于原点的头部,并且我们正在观察控制器在执行YAW时所发出的值。 PITCH ING。

在计算YAWPITCH值之前,尝试将所有内容放在标准化坐标中。让我们考虑一个具有以下坐标的矩形

Vertices:  X     Y     Z
      P1: 0.52   0.76  -2.40  //LeftTop
      P2: 0.52   0.21  -2.40  //LeftBottom
      P3: 1.54   0.21  -2.40  //RightBottom
      P4: 1.54   0.76  -2.40  //Right Top
Formula:  
    YAW: Math.atan2(x,-z)
  PITCH: Math.atan2(y,-z)
//Then yaw, pitch values for above vertices will be
         YAW   PITCH
     P1: 0.21  0.31  //LeftTop
     P2: 0.21  0.09  //LeftBottom
     P3: 0.57  0.09  //RightBottom
//We don't require P4 here
      YAW Left: 0.21 ( P2 or P1 YAW)
      YAW Right: 0.57 ( P3 YAW )
    PITCH Top: 0.31 ( P1 PITCH )
    PITCH Bottom: 0.09  ( P2 or P3 PITCH )
// let us find the pitch and yaw values of controllers as well
   angles = controller.orientation.toYawPitchRollRadians
   angles[0]: YAW
   angles[1]: PITCH
   angles[2]: ROLL
 //of controller
 // controller YAW moves positive to negative from left to right, but in 
 // normalized coordinates, negative to positive from left to right, so to 
 // match controller's YAW values
      YAW Left: 0.21 * -1 ( P2 or P1 YAW)
      YAW Right: 0.57 * -1 ( P3 YAW )
    PITCH Top: 0.31 ( P1 PITCH )
    PITCH Bottom: 0.09  ( P2 or P3 PITCH )
 // and to know whether the controller is at the rectangle or not we simply do
    public boolean isOnRectangle(float[] angles) {
    return angles[0] <= yawLeft && angles[0] >= yawRight
            && angles[1] <= pitchTop && angles[1] >= pitchBottom;
}

如果控制器指针落在矩形中,则上面将返回true,否则返回false。