以下是我的案例
left=0,right=1824,top=0,bottom=989
的长方形,宽高比1.84f,统一z axis = -3f
-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)
view = perspective ( z near 0.1f, far 100 f) * eye.getEyeVew
controllerMatrix = controller.toRotationMatrix
modelView = view * controllerMatrix
我的假设是,
所以,我的问题是为了这个目的,我应该去RayCasting还是有一个简单的解决方案,用VR控制器选择小矩形。
我正在使用GVR控制器( Google VR version 1.80.0 )
并使用Android进行应用开发。
谢谢
答案 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空间中矩形的中心点。
您还必须计算定义摄像机指向方向的矢量与矩形相交的角度。如下图所示:
此处原点是您的相机位置,C点是3D空间中渲染的矩形的质心,矢量 OC 是您的相机直接聚焦时指向的方向矢量矩形的中心。 Ꝋ是X-Z平面中从X轴到C点的角度。点P1-4是3D空间中矩形的顶点。
音高ɸ在下图中定义:
此处ɸ是从中心点 C 到新轴 e 的角度。
PITCH_LIMIT
是两个向量之间的Y- e 平面中的角度。从摄像机位置到对象边界框底边的矢量,以及从摄像机位置到对象边界框上边缘的矢量。在这种情况下,它可以计算为 OP3 和 OP4 之间的角度或 OP2 和 OP1 之间的角度。这在以下2D横截面中描述:
假设相机正在直视矩形,此限制定义了在相机中心不再直接指向矩形之前相机必须向上倾斜的程度。
YAW_LIMIT
是两个矢量之间XZ平面中的角度,从摄像机位置到对象边界框最左边缘的矢量,以及从摄像机位置到右边的矢量对象边界框的最边缘。在这种情况下,它可以计算为 OP1 和 OP4 之间的角度或 OP2 和 OP3 之间的角度。这在以下2D横截面中描述:
同样,此限制定义了在相机中心不再直接指向矩形之前,相机可以向左或向右旋转的程度。
请注意,如果您距离对象较远,YAW_LIMIT
和PITCH_LIMIT
值会变小,如果距离较近,则值会变大。您必须根据当前摄像机位置和对象的边缘顶点计算要查看的对象的这些限制。从对象空间到相机空间的坐标转换是在isLookingAtObject()
方法中处理的。
答案 1 :(得分:1)
首先,需要查看sparkplug提供的上述详细说明,其中包含与该问题相关的所有概念。而且我欠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
值。为了简化研究,将控制器平放在桌子上,触摸板远离您。然后按照您在表格中旋转瓶子的方式稍微向左和向右移动控制器。您会注意到YAW
值的范围。然后轻轻拿起控制器,然后上下移动。这将给出控制器的PITCH
值范围。为简单起见,我们的控制器将被设置为原点,或者为了使问题更简单,您可以将控制器视为位于原点的头部,并且我们正在观察控制器在执行YAW
时所发出的值。 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;
}
如果控制器指针落在矩形中,则上面将返回true,否则返回false。