Push/Pop 矩阵和单个对象在 OpenGL 中围绕其自己的轴旋转
Posted
技术标签:
【中文标题】Push/Pop 矩阵和单个对象在 OpenGL 中围绕其自己的轴旋转【英文标题】:Push/Pop matrix and individual object rotation around its own axis in OpenGL 【发布时间】:2012-02-22 16:57:09 【问题描述】:这已经被问过很多很多次了,我在互联网上阅读了大量关于它的帖子和论坛,但我就是无法让一个物体围绕它自己的轴旋转。 我有几个这样绘制的对象:
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
.....
gl.glPushMatrix();
gl.glRotatef(angle, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 0.0f);
texture.bind(gl);
gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, textureRLt);
gl.glNormalPointer(GL2.GL_FLOAT, 0, normalRLt);
gl.glVertexPointer(3, GL2.GL_FLOAT, 0, vertexRLt);
gl.glDrawElements(GL2.GL_TRIANGLES, countI, GL2.GL_UNSIGNED_SHORT, indexRLt);
gl.glPopMatrix();
这是正确绘制的,应用了所有纹理和法线..
我知道 OpenGL 会反向执行命令,所以这就是 glRotatef 优先的原因。我也知道所有的旋转都围绕原点,所以我需要将对象转换到那个原点(不是我认为我必须这样做,因为“笔”已经在原点,因为我在绘制每个对象之前保存了矩阵和之后弹出它)。是glDrawElements的东西吗?似乎有些不对劲。
任何帮助将不胜感激。 :)
编辑:我可以看到对象如何围绕主 x 轴旋转,但我希望它们围绕其局部 x 轴旋转。
【问题讨论】:
不是OpenGL“反向执行命令”,而是变换矩阵的组合方式。 您想要做的是将操作视为在本地而不是全局应用。因此,在您的示例中,您围绕本地 Y 轴旋转,然后在该新坐标系中进行平移。如果您希望旋转更本地化,则需要稍后完成。但是,在您的示例中,您的翻译为零,因此它无效,并且顺序无关紧要。也许你只是误解了对象的轴是什么。 【参考方案1】:“OpenGL 反向执行命令”,表示它是从右侧而不是左侧乘以变换矩阵。这是什么意思?
想象一下变换 A 和 B:
y = Ax
将x
转换为A
并产生y
这相当于:
// sudo code:
glA()
glDraw(x)
现在,通常,在编程中,你认为你得到转换是为了编写它们。所以,你认为
glA()
glB()
glDraw(x)
会给你
y = BAx
但这是错误的。你实际上得到:
y = ABx
这意味着,首先将B
应用于x
,然后将A
应用于结果。
换成英文,看看这个例子:
glScalef(...) // third, scale the whole thing
glTranslatef(...) // second, translate it somewhere
glRotatef(...) // first, rotate the object (or course,
// around its own axes, because the object is at origin)
glDrawElements(...) // draw everything at origin
所以,你需要做的就是写:
// When everything is drawn, move them to destination:
gl.glTranslatef(destination[0], destination[1], destination[2]);
// For every object, rotate it the way it should, then restore transformation matrix
// object: RLt
gl.glPushMatrix();
gl.glRotatef(angle, 0.0f, 1.0f, 0.0f);
texture.bind(gl);
gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, textureRLt);
gl.glNormalPointer(GL2.GL_FLOAT, 0, normalRLt);
gl.glVertexPointer(3, GL2.GL_FLOAT, 0, vertexRLt);
gl.glDrawElements(GL2.GL_TRIANGLES, countI, GL2.GL_UNSIGNED_SHORT, indexRLt);
gl.glPopMatrix();
// object: RLt2
gl.glPushMatrix();
gl.glRotatef(angle2, 0.0f, 1.0f, 0.0f);
texture.bind(gl);
gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, textureRLt2);
gl.glNormalPointer(GL2.GL_FLOAT, 0, normalRLt2);
gl.glVertexPointer(3, GL2.GL_FLOAT, 0, vertexRLt2);
gl.glDrawElements(GL2.GL_TRIANGLES, countI2, GL2.GL_UNSIGNED_SHORT, indexRLt2);
gl.glPopMatrix();
【讨论】:
感谢@Shahbaz 的快速反应!不幸的是,我之前尝试过(现在再次尝试,只是为了确保)但效果是一样的:(我在绘制任何东西之前添加了 gl.glTranslatef(0.0f, 0.0f, 0.0f)的openGL,在我画完所有东西之后)-一开始。效果是一样的;有一些奇怪的东西,即使在它只旋转一个对象之前,它是用glBegin而不是顶点数组绘制的 请注意,glTranslatef(0, 0, 0) 不会将对象带到原点,它只是将其移动 (0, 0, 0),这基本上意味着它什么都不做。如果你的对象在 (x, y, z),你应该用 (-x, -y, -z) 翻译它。请注意,如果您之前的转换包括旋转和缩放,这可能会变得非常复杂。在这种情况下,您最好的方法是从 opengl 获取转换矩阵,提取翻译部分并进行逆运算。 我确实怀疑过类似的事情。对于这么简单的事情来说,这是一个非常复杂的操作:D @Peter:其实你根本不用担心 glRotate、glTranslate、glScale。它们已完全从 OpenGL-3 中删除。相反,您应该自己构建矩阵。这比您想象的要容易。基本上你必须明白,矩阵的左上角 3×3 部分定义了旋转和缩放,而最右边的 1×3 部分定义了平移。底部的 4×1 应该保留为 (0,0,0,1) - 这只是为了使数学更好,并且主要与不同的值一起使用以在投影中创建透视效果。 @datenwolf,我最讨厌的是我对 OpenGL 编程的爱好突然完全被弃用了,我没有时间赶上 :-/【参考方案2】:我不确定您是否定期更新“角度”变量。如果你不是,那么就不会有任何轮换。伪代码如下。您可以使用 gluttimerfunc 定期更新变量。
for(每个 opengl 循环)
角度+=5.0f
萨蒂什
【讨论】:
以上是关于Push/Pop 矩阵和单个对象在 OpenGL 中围绕其自己的轴旋转的主要内容,如果未能解决你的问题,请参考以下文章