Ben*_*tto 23 opengl graphics transform
我有一些二维几何.我想在我的几何体周围采用一些边界矩形,然后在平面上的其他地方渲染一个较小的版本.这里或多或少是我必须进行缩放和翻译的代码:
// source and dest are arbitrary rectangles.
float scaleX = dest.width / source.width;
float scaleY = dest.height / source.height;
float translateX = dest.x - source.x;
float translateY = dest.y - source.y;
glScalef(scaleX, scaleY, 0.0);
glTranslatef(translateX, translateY, 0.0);
// Draw geometry in question with its normal verts.
当dest原点为0时,这与给定维度的预期完全一样.但是,如果x的原点非零,则结果仍然正确缩放但看起来像(?)它被转换为该轴上接近零的值无论如何 - 事实证明它与dest.x为零并不完全相同.
有人能指出一些我不知道的明显事物吗?
谢谢!
最终更新根据下面的Bahbar和Marcus的答案,我做了一些实验并解决了这个问题.亚当鲍文的评论是提示.我错过了两个重要的事实:
回想起来,第一种是显而易见的.但对于后者,对于像我这样的其他优秀程序员/坏数学家:原来我的直觉是在红皮书所谓的"大型,固定坐标系统"中运行,其中有一个绝对平面,你的几何形状在四处移动那架飞机使用变形.这是可以的,但考虑到将多个变换堆叠成一个矩阵背后的数学性质,它与事物真正起作用的方式相反(请参阅下面的答案或红皮书了解更多信息).基本上,变换以"相反的顺序""应用"它们在代码中的出现方式.这是最终的工作解决方案:
// source and dest are arbitrary rectangles.
float scaleX = dest.width / source.width;
float scaleY = dest.height / source.height;
Point sourceCenter = centerPointOfRect(source);
Point destCenter = centerPointOfRect(dest);
glTranslatef(destCenter.x, destCenter.y, 0.0);
glScalef(scaleX, scaleY, 0.0);
glTranslatef(sourceCenter.x * -1.0, sourceCenter.y * -1.0, 0.0);
// Draw geometry in question with its normal verts.
Mac*_*cke 18
在OpenGL中,您指定的矩阵乘以现有矩阵的右侧,顶点位于表达式的最右侧.
因此,您指定的最后一个操作位于几何体本身的坐标系中.(第一种通常是视图变换,即相机到世界变换的反转.)
Bahbar提出了一个很好的观点,你需要考虑缩放的中心点.(或旋转的枢轴点.)通常你在那里翻译,旋转/缩放,然后翻译回来.(或者一般来说,应用基础变换,操作,然后反过来).这称为基础变更,您可能需要阅读.
无论如何,要获得一些关于它是如何工作的直觉,尝试使用一些简单的值(零等)然后稍微改变它们(可能是一个动画),看看输出会发生什么.然后,您可以更轻松地查看转换对您的几何体实际执行的操作.
更新
在初学者OpenGL编码器中,命令是"逆转"的直觉是相当普遍的.我一直在辅导计算机图形学课程,许多人以类似的方式做出反应.如果在渲染变换和几何的树(场景图)时考虑使用pushmatrix/popmatrix,则更容易思考OpenGL如何做到这一点.然后,当前的事物顺序变得相当自然,相反的情况会使得完成任何有用的事情变得相当困难.
缩放,就像旋转一样,从原点开始运作.所以,如果你缩放一半跨越段[10:20]的对象(例如,在X轴上),你得到[5:10].因此,物体被缩放,并移近原点.正是你所观察到的.
这就是你通常首先应用Scale的原因(因为对象往往定义在0左右).
因此,如果要围绕点中心缩放对象,可以将对象从中心转换为原点,在那里缩放,然后进行平移.
旁注,如果先翻译,然后进行缩放,那么您的比例将应用于上一个翻译,这就是您可能遇到此方法问题的原因.