OpenGL 变换(如 glScale、glTranslate 等)

4

我正在学习OpenGL以及如何进行变换,例如平移和缩放。我知道通常需要先将图形平移到原点,然后进行所需的操作(比如缩放),最后再平移回去。根据我的理解,这是手动完成的,但你也可以使用glScale()函数来完成同样的操作。

我的问题是,如果我使用glScale()函数,是否仍然需要将图形平移到原点并返回?

3个回答

16

你可能不需要对原点进行任何翻译,只需按所需顺序进行转换即可。请记住,应用的最后一个转换发生在之前所有转换的转换空间中。例如:

// draw object centred on (1,2,3) and ten times bigger
glTranslatef(1,2,3);
glScalef(10,10,10);
drawObject();

对比

// draw object centred on (10,20,30) and ten times bigger
glScalef(10,10,10);
glTranslatef(1,2,3);
drawObject();
在第二个示例中,翻译和对象都放大了10倍,因为它们是在缩放之后进行的。(这种方案允许drawObject()包括变换并仍然像单个单位一样运行。)

在第二个示例中,由于它们是在缩放之后完成的,所以翻译和对象都被放大了10倍。(这种方案使得drawObject()可以包括变换,并仍然像单个单位一样运行。)


好的,非常感谢,这对我很有帮助。所以基本上我只需要按顺序进行变换,即:平移->缩放->旋转,但是我不必将物体先平移到原点再移回来,因为似乎gl函数已经自动帮我们处理了这个问题。 - Katianie
3
不,它们不会为你做这件事情,但通常这并不重要。这里没有确定的规则:你需要了解正在发生的事情。例如,如果你想让一颗行星绕着太阳运转,你需要先进行旋转,然后再进行平移。平移的方向将会受到之前旋转的影响,就像你想要的那样。但对于行星自身的日常旋转,你需要在平移后进行另一次旋转。希望这有意义。 - Martin Stone
在第一个示例中,我们先缩放再平移,在第二个示例中,我们先平移到1、2、3然后再缩放,这样如何将对象绘制在10、20、30的位置上? - vexe
翻译是与对象一起缩放的。 - Martin Stone

3

您需要考虑堆栈上发生的转换。换句话说,您指定的最后一个转换首先发生。因此,

glTranslatef(1,2,3);
glScalef(10,10,10);
glRotatef(45,1,0,0);
drawObject();

这段代码首先会绕x轴旋转45度,然后将对象缩放到(10,10,10),最后平移至(1,2,3)。但是,您还需要记住,任何应用的变换都会影响到后续的变换。如果我们反转上述变换的顺序,则旋转将围绕不同的点旋转。


3

glScale的作用只是将当前矩阵乘以一个缩放矩阵。因此,如果您想要做的就是这样,那么在应用平移之前应该应用缩放矩阵。

另请参阅glScale参考文档


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接