如何在全局轴上旋转图形,而不是局部轴?
Posted
技术标签:
【中文标题】如何在全局轴上旋转图形,而不是局部轴?【英文标题】:How to rotate a graphic over global axes, and not to local axes? 【发布时间】:2013-04-27 00:12:52 【问题描述】:我认为我的问题很简单,但我是 Opengl 的新手,我不知道该怎么办。
我正在尝试旋转金字塔(数字无关紧要),我想相对于 X 旋转 然后相对于 Y 轴旋转。
但是当我在 X 上旋转时,Y 轴也会旋转。然后当我想相对于 Y 旋转一点时,Y 轴不再是原来的了。
下一张图片显示了米金字塔在原点的星形:
然后相对于 X 旋转 winth:
Y轴和Z轴也旋转,然后如果我想相对于Y旋转,金字塔相对于旋转的Y轴旋转,而不是原来的Y轴旋转(深绿色)。
我使用 PushMatrix();和流行矩阵(); :
gl.PushMatrix();
gl.Rotate(bx, 1.0f, 0.0f, 0.0f);
gl.PushMatrix();
gl.Rotate(by, 0.0f, 1.0f, 0.0f);
//Pyramid
gl.Begin(OpenGL.GL_TRIANGLES);
gl.Color(1.0f, 0.0f, 0.0f);
gl.Vertex(0.0f, 1.0f, 0.0f);
gl.Vertex(-1.0f, -1.0f, 1.0f);
gl.Vertex(1.0f, -1.0f, 1.0f);
gl.Color(0.0f, 1.0f, 0.0f);
gl.Vertex(0.0f, 1.0f, 0.0f);
gl.Vertex(1.0f, -1.0f, 1.0f);
gl.Vertex(1.0f, -1.0f, -1.0f);
gl.Color(0.0f, 0.0f, 1.0f);
gl.Vertex(0.0f, 1.0f, 0.0f);
gl.Vertex(1.0f, -1.0f, -1.0f);
gl.Vertex(-1.0f, -1.0f, -1.0f);
gl.Color(1.0f, 1.0f, 1.0f);
gl.Vertex(0.0f, 1.0f, 0.0f);
gl.Vertex(-1.0f, -1.0f, -1.0f);
gl.Vertex(-1.0f, -1.0f, 1.0f);
gl.End();
gl.PopMatrix();
gl.PopMatrix();
bx 和 by 只是在您单击按钮时增加或减少角度(现在 Z 无关紧要)
我想相对于 X 和 Y 旋转金字塔,但原始轴(万向轴)独立于局部轴。
注意:我使用的是 SharpGL(用于 c# 的 OpenGL),但它是一样的。
更新
我更改了我的代码:
gl.PushMatrix();
gl.Rotate(bx, 1.0f, 0.0f, 0.0f);
gl.PushMatrix();
//gl.Rotate(by, 0.0f, 1.0f, 0.0f); This changes
gl.Rotate(by, 0.0f, Math.Cos(bx*Math.PI / 180), -Math.Sin(bx*Math.PI / 180));
//Pyramid
gl.PopMatrix();
gl.PopMatrix();
我乘以矩阵Rx逆[1 0 0; 0 余弦; 0 -Sin Cos] 由向量 Y [0 1 0] 得到,得到的向量 [0 Cos -Sin] 由 Y 旋转。
这按我的意愿工作,我按 X 旋转,在按 Y 旋转之后,但是当我按 X 再旋转时,现在旋转是按 X 旋转而不是相对于原始旋转!!!,但 Y 的旋转保持不变。
还有什么想法吗??非常感谢!!!
【问题讨论】:
您必须将全局x
轴解析为局部坐标才能进行旋转。
【参考方案1】:
操作的顺序很重要,根据 OpenGL 中使用的语义,实际转换的应用顺序与它们在代码中发生的顺序相反。因此,如果您想先按 X 旋转,然后按 Y 旋转,则 Y 旋转必须在您的代码中排在第一位。
更深层的原因是 OpenGL 使用(出于各种合理的原因)列主要的右关联矩阵排序。像
这样的转换链MV = V · M · R_x · R_y
将在列(位置)向量中从右向左相乘,即
MV · ↑v
分解成
V · ( M · ( R_x · ( R_y · ↑v ) ) )
并且由于矩阵不是阿贝尔矩阵,因此有无数个矩阵 A、B
A · B =/= B · A
【讨论】:
如果我先按 Y 旋转,我会遇到同样的问题,但现在 X 轴旋转了,它不是原来的。我只想按原来的 X 和 Y 旋转,与应用的旋转无关 @Johnnie90:嗯,当您使用 OpenGL 内置函数应用变换时,它会修改相对于下一个变换的局部坐标系。对于您想要的,您必须执行左侧乘法。如果您想为此使用 OpenGL 的矩阵数学函数,这将非常麻烦。更简单的解决方案是使用一些真正的矩阵数学库,如 GLM、Eigen 或我的 linmath.h。如果您查看上面的方程式,您会在 M 之后插入每个新的旋转【参考方案2】:我最近遇到了这个问题并最终得到了这个解决方案:
-
使用
glRotate(bx,1f,0f,0f);
围绕局部 x 轴旋转。
计算局部坐标系ux=0
、uy=cos(bx)
、uz=sin(bx)
中的全局y轴分量。
使用glRotate(by,ux,uy,uz);
围绕局部轴旋转。
注意需要的函数是
Func<float,float> cos = (x)=>(float)(Math.Cos(x*Math.PI/180));
Func<float,float> sin = (x)=>(float)(Math.Sin(x*Math.PI/180));
要将角度转换为弧度,取 sin 和 cos 并返回一个浮点数。
【讨论】:
谢谢,但这不起作用,旋转尊重 Y 不是原始 Y。 我修复了一个错误。uz=sin(bx)
而不是 uz=sin(by)
。我的错。这应该可以解决 OP 问题。以上是关于如何在全局轴上旋转图形,而不是局部轴?的主要内容,如果未能解决你的问题,请参考以下文章