Google VR如何用daydream控制器进行选择
Google VR how to perform selection with daydream controller
以下是我的案例
- 我有一个
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 axis
和 1 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平面来选择。
- 我假设圆的二维坐标(left,top,right,bottom)可以用来和平面二维坐标(left,top,right,bottom)核对,看圆是否落在平面上或不。
- 但是由于透视和eye.getEyeView变换,圆和平面的z轴都发生了变化。
因此,我的问题是为此目的我应该选择 RayCasting 还是有一个简单的解决方案来选择带有 VR 控制器的小矩形。
我正在使用 GVR 控制器 ( Google VR version 1.80.0 )
并使用 Android 进行应用程序开发。
谢谢
Google VR SDK 附带了一些有用的示例项目,演示了如何实现这一点。如果您检查 Treasure Hunt project,TreasureHuntActivity
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 平面中两个向量之间的夹角。从相机位置到对象边界框下边缘的向量和从相机位置到对象边界框上边缘的向量。在这种情况下,它可以计算为 OP3 和 OP4 之间的角度或 OP2 之间的角度和 OP1。这在以下二维横截面中进行了描述:
假设相机直视矩形,这个限制定义了在相机中心不再直接指向矩形之前相机必须向上倾斜的程度。
YAW_LIMIT
是两个向量在X-Z平面内的夹角,从相机位置到物体边界框最左边缘的向量,从相机位置到物体边界框最左边缘的向量对象边界框的最右边缘。在这种情况下,它可以计算为 OP1 和 OP4 之间的角度或 OP2 之间的角度和 OP3。这在以下二维横截面中进行了描述:
同样,此限制定义了在相机中心不再直接指向矩形之前相机可以向左或向右旋转多少。
请注意,如果您离对象较远,YAW_LIMIT
和 PITCH_LIMIT
值会变小,如果距离较近,则值会变大。您必须根据当前相机位置和对象的边缘顶点计算要检查的对象的这些限制。从对象 space 到相机 space 的坐标转换在 isLookingAtObject()
方法中处理。
首先,需要看一下sparkplug, which contains all the concepts related to the question. And I owe sparkplug提供的上述详细描述,提供了与此问题相关的如此伟大的概念,没有谁,将无法找到答案。
继续,如果您无法理解 atan2
的作用,请按照此 link 进行操作。根据三角公式 tan(angle) = perpendicular/base
并且如果您有 perpendicular
和 base
值 atan2
将给出角度。基本上 atan2
会给出两点之间的角度。在我们的例子中,点 1 是原点 0,0,0
,其他点是矩形的中心点或矩形的任何顶点。因此矩形中的原点和点之间的差异将只是点值,即 x-0 = x, y-0 = y, z-0 = z
。此外,在我们的例子中,我们正在参考 z axis
计算角度,即我们的 base
.
如果你对YAW
和PITCH
的概念理解有些困难,我就打个脑袋运动的类比。把头伸直,看向前方,然后向左转头,再向右转头。这是 YAW
即你的头在左右方向移动的角度。再次让你的头直视前方,然后上下移动你的头。这是 PITCH
即你的头上下移动的角度。
类比头部运动,你的脖子和头部之间的点就是轴心点。上下移动你的头,你的眼睛将扫视 PITCH
方向。同样,采用相同的轴心点,将头部从左向右移动,您的眼睛将扫视 YAW
方向。
在此解决方案中,我们需要计算移动头部的角度以扫描整个矩形的宽度和高度。
继续,采用上面的类比并研究 daydream controller sample。你需要研究它给出的 YAW
和 PITCH
值。为了简化学习,将控制器平放在 table 中,触摸板远离您。然后按照你在 table 中旋转瓶子的方式在左右方向稍微移动控制器。您会注意到 YAW
值的范围。然后轻轻拿起控制器上下移动即可。这将给出控制器的 PITCH
值范围。为了简单起见,我们的控制器将被设置为原点,或者为了使问题更简单,您可以将控制器视为位于原点的头部,我们正在观察控制器在执行 YAW
ing 和PITCH
ing.
在计算 YAW
和 PITCH
值之前,尝试将所有内容都放在标准化坐标中。让我们考虑一个具有以下坐标的矩形
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 为真,否则为假。
以下是我的案例
- 我有一个
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 axis
和1 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平面来选择。
- 我假设圆的二维坐标(left,top,right,bottom)可以用来和平面二维坐标(left,top,right,bottom)核对,看圆是否落在平面上或不。
- 但是由于透视和eye.getEyeView变换,圆和平面的z轴都发生了变化。
因此,我的问题是为此目的我应该选择 RayCasting 还是有一个简单的解决方案来选择带有 VR 控制器的小矩形。
我正在使用 GVR 控制器 ( Google VR version 1.80.0 )
并使用 Android 进行应用程序开发。
谢谢
Google VR SDK 附带了一些有用的示例项目,演示了如何实现这一点。如果您检查 Treasure Hunt project,TreasureHuntActivity
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 平面中两个向量之间的夹角。从相机位置到对象边界框下边缘的向量和从相机位置到对象边界框上边缘的向量。在这种情况下,它可以计算为 OP3 和 OP4 之间的角度或 OP2 之间的角度和 OP1。这在以下二维横截面中进行了描述:
假设相机直视矩形,这个限制定义了在相机中心不再直接指向矩形之前相机必须向上倾斜的程度。
YAW_LIMIT
是两个向量在X-Z平面内的夹角,从相机位置到物体边界框最左边缘的向量,从相机位置到物体边界框最左边缘的向量对象边界框的最右边缘。在这种情况下,它可以计算为 OP1 和 OP4 之间的角度或 OP2 之间的角度和 OP3。这在以下二维横截面中进行了描述:
同样,此限制定义了在相机中心不再直接指向矩形之前相机可以向左或向右旋转多少。
请注意,如果您离对象较远,YAW_LIMIT
和 PITCH_LIMIT
值会变小,如果距离较近,则值会变大。您必须根据当前相机位置和对象的边缘顶点计算要检查的对象的这些限制。从对象 space 到相机 space 的坐标转换在 isLookingAtObject()
方法中处理。
首先,需要看一下sparkplug, which contains all the concepts related to the question. And I owe sparkplug提供的上述详细描述,提供了与此问题相关的如此伟大的概念,没有谁,将无法找到答案。
继续,如果您无法理解 atan2
的作用,请按照此 link 进行操作。根据三角公式 tan(angle) = perpendicular/base
并且如果您有 perpendicular
和 base
值 atan2
将给出角度。基本上 atan2
会给出两点之间的角度。在我们的例子中,点 1 是原点 0,0,0
,其他点是矩形的中心点或矩形的任何顶点。因此矩形中的原点和点之间的差异将只是点值,即 x-0 = x, y-0 = y, z-0 = z
。此外,在我们的例子中,我们正在参考 z axis
计算角度,即我们的 base
.
如果你对YAW
和PITCH
的概念理解有些困难,我就打个脑袋运动的类比。把头伸直,看向前方,然后向左转头,再向右转头。这是 YAW
即你的头在左右方向移动的角度。再次让你的头直视前方,然后上下移动你的头。这是 PITCH
即你的头上下移动的角度。
类比头部运动,你的脖子和头部之间的点就是轴心点。上下移动你的头,你的眼睛将扫视 PITCH
方向。同样,采用相同的轴心点,将头部从左向右移动,您的眼睛将扫视 YAW
方向。
在此解决方案中,我们需要计算移动头部的角度以扫描整个矩形的宽度和高度。
继续,采用上面的类比并研究 daydream controller sample。你需要研究它给出的 YAW
和 PITCH
值。为了简化学习,将控制器平放在 table 中,触摸板远离您。然后按照你在 table 中旋转瓶子的方式在左右方向稍微移动控制器。您会注意到 YAW
值的范围。然后轻轻拿起控制器上下移动即可。这将给出控制器的 PITCH
值范围。为了简单起见,我们的控制器将被设置为原点,或者为了使问题更简单,您可以将控制器视为位于原点的头部,我们正在观察控制器在执行 YAW
ing 和PITCH
ing.
在计算 YAW
和 PITCH
值之前,尝试将所有内容都放在标准化坐标中。让我们考虑一个具有以下坐标的矩形
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 为真,否则为假。