OpenGL:缩放然后平移?怎么做?
我有一些二维几何图形。我想在几何体周围使用一些边界矩形,然后在平面上的其他地方渲染它的较小版本。以下是我必须进行缩放和转换的代码:OpenGL:缩放然后平移?怎么做?,opengl,graphics,transform,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 translate
// 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.
“缩放”与“旋转”一样,从原点开始操作。因此,如果将跨越段[10:20]的对象缩放一半(例如,在X轴上),则得到[5:10]。因此,对象被缩放,并移近原点。正是你观察到的 这就是为什么通常首先应用“缩放”(因为对象往往在0左右定义) 因此,如果要围绕点中心缩放对象,可以将对象从中心平移到原点,在那里缩放,然后向后平移
旁注,如果先平移,然后缩放,则缩放将应用于上一次的平移,这就是您可能会遇到此方法问题的原因。在OpenGL中,您指定的矩阵将相乘到现有矩阵的右侧,并且顶点位于表达式的最右侧 因此,您指定的最后一个操作在几何体本身的坐标系中。 (第一种通常是视图变换,即相机到世界变换的逆变换。) BaBar提出了一个很好的观点,你需要考虑缩放的中心点。(或旋转的轴心点。)通常在那里平移,旋转/缩放,然后向后平移。(或者通常,应用基础变换、运算,然后是逆运算)。这就是所谓的,你可能想读一读 无论如何,为了获得一些关于它如何工作的直觉,尝试使用一些简单的值(零等),然后稍微改变它们(可能是动画),看看输出会发生什么。这样就更容易看到变换对几何体的实际作用 更新
在OpenGL初学者中,直觉的顺序是“颠倒的”。我一直在教一门计算机图形学课程,很多人的反应都类似。如果你考虑使用PuxMask/PopMatLs来渲染树(场景图)的变换和几何图形,那么OpenGL是如何变得更容易的。然后,当前的事情顺序变得相当自然,反之则会使做任何有用的事情变得相当困难。我没有玩过OpenGL ES,只玩过一点OpenGL 听起来你想从与原点相反的不同位置变换,不确定,但你能尝试进行变换并在其中绘制该位吗 下面是我为说明这一点而编写的一个简单的处理示意图:
import processing.opengl.*;
import javax.media.opengl.*;
void setup() {
size(500, 400, OPENGL);
}
void draw() {
background(255);
PGraphicsOpenGL pgl = (PGraphicsOpenGL) g;
GL gl = pgl.beginGL();
gl.glPushMatrix();
//transform the 'pivot'
gl.glTranslatef(100,100,0);
gl.glScalef(10,10,10);
//draw something from the 'pivot'
gl.glColor3f(0, 0.77, 0);
drawTriangle(gl);
gl.glPopMatrix();
//matrix poped, we're back to orginin(0,0,0), continue as normal
gl.glColor3f(0.77, 0, 0);
drawTriangle(gl);
pgl.endGL();
}
void drawTriangle(GL gl){
gl.glBegin(GL.GL_TRIANGLES);
gl.glVertex2i(10, 0);
gl.glVertex2i(0, 20);
gl.glVertex2i(20, 20);
gl.glEnd();
}
这是草图运行的图像,绘制了相同的绿色三角形,应用了平移和缩放,然后是红色三角形,超出了推/弹出“块”,因此不受变换的影响:
嗯,,
乔治谢谢你的答复。你能为一个矩阵数学的傻瓜解释一下我会做什么操作,做适当的转换到原点,然后缩放,再转换回原点吗?在绘制几何体之前,我尝试在三次调用中依次叠加这三件事(按源原点的负数平移,然后按比例因子缩放,然后按目标原点平移),但没有得到明显的结果。啊,也许我需要相对于矩形的中心而不是原点进行平移。我会试试这个。不。无骰子:按源的负中心平移,然后缩放,然后按目标的正中心平移。简言之,将顺序更改为GLTRANSE(目标);glScale(量表);glTranslate(来源);亚当:这似乎不像你所说的那样有效,尽管我很好奇——你能详细解释一下为什么排序会是这样的吗?也许能提供一个更明确的想法,说明与现有代码相比,排序会是怎样的?也许我只是误解了你的伪代码。谢谢Nevermind:在本例中,“不起作用”是一个命中注定的值。修好之后,我们就开始做生意了。有关更多信息,请参阅更新的问题。谢谢谢谢George,但是推送/弹出并不是真正的问题;我已经在编写代码片段的代码之外进行了推/弹出操作。不过,感谢您用图片进行说明!很好的视觉效果。
import processing.opengl.*;
import javax.media.opengl.*;
void setup() {
size(500, 400, OPENGL);
}
void draw() {
background(255);
PGraphicsOpenGL pgl = (PGraphicsOpenGL) g;
GL gl = pgl.beginGL();
gl.glPushMatrix();
//transform the 'pivot'
gl.glTranslatef(100,100,0);
gl.glScalef(10,10,10);
//draw something from the 'pivot'
gl.glColor3f(0, 0.77, 0);
drawTriangle(gl);
gl.glPopMatrix();
//matrix poped, we're back to orginin(0,0,0), continue as normal
gl.glColor3f(0.77, 0, 0);
drawTriangle(gl);
pgl.endGL();
}
void drawTriangle(GL gl){
gl.glBegin(GL.GL_TRIANGLES);
gl.glVertex2i(10, 0);
gl.glVertex2i(0, 20);
gl.glVertex2i(20, 20);
gl.glEnd();
}