我正在尝试使用iPhone的运动管理器对象创建一个VR应用程序。我所说的VR是指一个在摄像头上显示地点的应用程序。
我可以成功地使用Z轴的偏航、俯仰和滚动来可视化iPhone的方向->X->Y旋转顺序。
以下是我迄今为止所做的事情的图片:
因此,我可以旋转设备,它将在我为监控而创建的Windows应用程序中正确旋转。
这是正确的,稍后我将显示代码。但这不是我想做的。
我想做的其实与此相反。我不想让设备移动。我希望它周围的世界旋转。所以,如果用户将相机指向东方,他应该看到“东方标志”,如果他将方向改为北方,他应该在屏幕上看到“北方标志”。但准确。不像其他应用程序那样取消了滚动运动。
这里的问题是,当我将设备从放在桌子上移动到纵向模式时,向右和向左旋转会导致旋转不正确。如果我把它放在横向模式,那么从上到下的旋转是不正确的。换言之,旋转是基于世界轴的,只有当设备放置在地面上时,旋转才会正确。因为这是我认为的参考系。
这里我想问的是如何转换这些角度,这样我就能看到我期望的结果。应该有一种基于三角的方法。
这些是我用来计算旋转矩阵的函数:
private static Matrix4 CreateRotationMatrix(char axis, float radians, bool rightHanded = true)
{
float c = (float)Math.Cos(radians);
float s = (float)Math.Sin(radians) * (rightHanded ? 1 : -1);
switch (axis)
{
case 'X':
return new Matrix4(
new Vector4(1.0f, 0.0f, 0.0f, 0.0f),
new Vector4(0.0f, c, -s, 0.0f),
new Vector4(0.0f, s, c, 0.0f),
new Vector4(0.0f, 0.0f, 0.0f, 1.0f));
case 'Y':
return new Matrix4(
new Vector4(c, 0.0f, s, 0.0f),
new Vector4(0.0f, 1.0f, 0.0f, 0.0f),
new Vector4(-s, 0.0f, c, 0.0f),
new Vector4(0.0f, 0.0f, 0.0f, 1.0f));
case 'Z':
return new Matrix4(
new Vector4(c, -s, 0.0f, 0.0f),
new Vector4(s, c, 0.0f, 0.0f),
new Vector4(0.0f, 0.0f, 1.0f, 0.0f),
new Vector4(0.0f, 0.0f, 0.0f, 1.0f));
default:
return Matrix4.Identity;
}
}
public static Matrix4 MatrixFromEulerAngles(
Vector3 euler,
string order,
bool isRightHanded = true,
bool isIntrinsic = true)
{
if (order.Length != 3) throw new ArgumentOutOfRangeException("order", "String must have exactly 3 charecters");
// X = Pitch
// Y = Yaw
// Z = Roll
return isIntrinsic
? CreateRotationMatrix(order[2], GetEulerAngle(order[2], euler), isRightHanded)
* CreateRotationMatrix(order[1], GetEulerAngle(order[1], euler), isRightHanded)
* CreateRotationMatrix(order[0], GetEulerAngle(order[0], euler), isRightHanded)
: CreateRotationMatrix(order[0], GetEulerAngle(order[0], euler), isRightHanded)
* CreateRotationMatrix(order[1], GetEulerAngle(order[1], euler), isRightHanded)
* CreateRotationMatrix(order[2], GetEulerAngle(order[2], euler), isRightHanded);
}
private static float GetEulerAngle(char angle, Vector3 euler)
{
switch (angle)
{
case 'X':
return euler.X;
case 'Y':
return euler.Y;
case 'Z':
return euler.Z;
default:
return 0f;
}
}
这就是我如何将矩阵应用于OpenGL:
Matrix4 projectionMatrix = Helper.MatrixFromEulerAngles(new Vector3(pitch, yaw, roll), "YXZ", true, true);
GL.LoadMatrix(ref projectionMatrix);