所以这是我的问题.我想在我的2D环境中显示一些3d点(例如winform或图像);
为此,我编写了这个函数:(它在C#中并使用OpenTK(OpenGL包装器)但我相信如果您了解OpenGL,无论您对C#有何了解,都可以理解它)
private Vector3 GetProjectedLocation( Vector3 pointPosition,Vector3 cameraPosition,Matrix4 cameraRotationMatrix) { float horizentalFov = MathHelper.degreesToradians(60.0f); float viewRatio = (float)this.RenderSize.Width / this.RenderSize.Height; Vector3 cameraReference = new Vector3(0,-1); Vector3 transformedReference = Vector3.Transform(cameraReference,Matrix4.Invert(cameraRotationMatrix)); Vector3 cameraLookatTarget = cameraPosition + transformedReference; Matrix4 modelMatrix = Matrix4.Identity; Matrix4 viewMatrix = Matrix4.LookAt(cameraPosition,cameraLookatTarget,new Vector3(0,1,0)); Matrix4 projectionMatrix = Matrix4.CreatePerspectiveFieldOfView(horizentalFov,viewRatio,0.1f,100.0f); Matrix4 viewmodelMatrix = viewMatrix * modelMatrix; return Helper.Project( pointPosition,viewmodelMatrix,projectionMatrix,new Rectangle(new Point(),this.RenderSize)); }
我还写了另一个名为Project cuz的函数我没有在OpenTK中找到它:
public static Vector3 Project(Vector3 point,Matrix4 viewmodel,Matrix4 projection,Rectangle viewport) { Vector4 point4 = new Vector4(point,1.0f); Vector4 pointModel = Vector4.Transform(point4,viewmodel); Vector4 pointProjection = Vector4.Transform(pointModel,projection); pointProjection.W = (float)(1.0 / pointProjection.W); pointProjection.X *= pointProjection.W; pointProjection.Y *= pointProjection.W; pointProjection.Z *= pointProjection.W; return new Vector3 { X = (float)((pointProjection.X * 0.5 + 0.5) * viewport.Width + viewport.X),Y = (float)((pointProjection.Y * 0.5 + 0.5) * viewport.Height + viewport.Y),Z = (float)((1.0 + pointProjection.Z) * 0.5) }; }
当所有三个值(偏航,俯仰和滚动)都为零时,它似乎按预期工作.我可以通过改变偏航和使用音高值垂直移动水平点.滚动也按照它应该的方式移动它.
当我将音高设置为90度时,问题就出现了.在这种情况下,偏航而不是水平移动,垂直移动,更糟糕的是,仅将其向下移动.无论我走向正面还是负面(-20度或20度)它总是会下降.有趣的是,当音高为90度时,Roll具有相同的效果,它只能像偏航那样垂直向下移动.将音高设置为-90deg具有相同的效果,但此时的偏航和滚动仅将其向上移动.
当我的两个轴平行时我看起来像万向节锁定问题而我丢失了一个方向,在这种情况下是滚动.我仍然不明白为什么偏航只能朝一个方向发挥作用.
无论如何,问题在于这种锁定在垂直查看时发生,这是我的程序在大多数时间看起来的地方.我已经读过如果我改变旋转顺序,我可以将万向节锁移到顶部(不太常见的地方).我尝试过多次订单而找不到好订单.所以这是我的代码,也许我做错了:
private Matrix4 CreateRotationMatrix(char axis,float radians) { float c = (float)Math.Cos(radians); float s = (float)Math.Sin(radians); if (axis == 'X') { return new Matrix4(1.0f,0.0f,c,-s,s,1.0f); } if (axis == 'Y') { return new Matrix4(c,1.0f,1.0f); } return new Matrix4(c,1.0f); } private Matrix4 MatrixFromEulerAngles(Vector3 euler,string order) { return CreateRotationMatrix(order[2],GetEulerAngle(order[2],euler)) * CreateRotationMatrix(order[1],GetEulerAngle(order[1],euler)) * CreateRotationMatrix(order[0],GetEulerAngle(order[0],euler)); } private float GetEulerAngle(char angle,Vector3 euler) { if (angle == 'X') return euler.X; if (angle == 'Y') return euler.Y; return angle == 'Z' ? euler.Z : 0f; }
你有什么主意吗?
以下是我知道的订单:
“XYZ”,“XZY”,“YXZ”,“YZX”,“ZXY”,“ZYX”
我可以提供一个示例程序来自己查看问题.
解决方法
相反,尝试将LookAt函数的“向上”向量计算为:
Vector3 localUpVec = Vector3.Transform(new Vector3(0,0),Matrix4.Invert(cameraRotationMatrix)); Matrix4 viewMatrix = Matrix4.LookAt(cameraPosition,localUpVec);
或者甚至更好,您可以完全绕过LookAt功能并自行计算:
Matrix4 viewMatrix = Matrix4.Subtract( Matrix4.Transpose(cameraRotationMatrix),Matrix4.Translation(cameraPosition) );
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。