Google VR如何用daydream控制器进行选择

Google VR how to perform selection with daydream controller

以下是我的案例

我的假设如下,

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

谢谢

Google VR SDK 附带了一些有用的示例项目,演示了如何实现这一点。如果您检查 Treasure Hunt projectTreasureHuntActivity class 有一个方法 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 矩形的中心点 space.

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

这里的原点是你的相机位置,点 C 是 3D 渲染矩形的质心 space 向量 OC 是你相机的方向向量当它直接聚焦在矩形的中心时指向。 Ꝋ 是 X 轴到 X-Z 平面中 C 点的夹角。点 P1-4 是 3D 矩形的顶点 space。

音高ɸ定义如下图:

这里的ɸ是中心点C到新坐标轴e.

的夹角

PITCH_LIMIT 是 Y-e 平面中两个向量之间的夹角。从相机位置到对象边界框下边缘的向量和从相机位置到对象边界框上边缘的向量。在这种情况下,它可以计算为 OP3OP4 之间的角度或 OP2 之间的角度和 OP1。这在以下二维横截面中进行了描述:

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

YAW_LIMIT是两个向量在X-Z平面内的夹角,从相机位置到物体边界框最左边缘的向量,从相机位置到物体边界框最左边缘的向量对象边界框的最右边缘。在这种情况下,它可以计算为 OP1OP4 之间的角度或 OP2 之间的角度和 OP3。这在以下二维横截面中进行了描述:

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

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

首先,需要看一下sparkplug, which contains all the concepts related to the question. And I owe 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 值。为了简化学习,将控制器平放在 table 中,触摸板远离您。然后按照你在 table 中旋转瓶子的方式在左右方向稍微移动控制器。您会注意到 YAW 值的范围。然后轻轻拿起控制器上下移动即可。这将给出控制器的 PITCH 值范围。为了简单起见,我们的控制器将被设置为原点,或者为了使问题更简单,您可以将控制器视为位于原点的头部,我们正在观察控制器在执行 YAWing 和PITCHing.

在计算 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;
}

如果控制器指针落在矩形内,以上将 return 为真,否则为假。