我正在尝试使用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);
答案 0 :(得分:0)
好的,反转是答案的一部分。它帮助了很多。感谢@dari和@Spektre的建议。
但完整的答案是,改变旋转方向(右手 - >左手),改变旋转顺序(YXZ - > ZXY,换句话说,Intrinsic to Extrinsic)和反转结果矩阵。 在询问之前,我曾单独尝试过这三个,但从未想过将它们全部一起使用。
所以:
Matrix4 projectionMatrix = Helper.MatrixFromEulerAngles(new Vector3(pitch, yaw, roll), "YXZ", false, false);
projectionMatrix.Invert();
GL.LoadMatrix(ref projectionMatrix);