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 中围绕其自己的轴旋转的主要内容,如果未能解决你的问题,请参考以下文章

js 类数组有push pop方法吗

如何计算线性锥形变换矩阵

JavaScript中push ,pop ,concat ,join方法

javascript之活灵活现的Array

OpenGL 矩阵变换

OpenGL矩阵乘法C++