在OpenGL中,我试图反转y轴,并设置一种特定类型的坐标系,就像Allegro一样。假设我的窗口是640x480,我希望屏幕的左上角是轴(0,0),右下角是(640,480)。到目前为止,我设法获得了我想要的正确坐标系,但我不知道它是否以正确的方式完成。至于翻转y轴,我无法在不修改我当前拥有的坐标系的情况下将其反转。我不希望只有翻转1个形状的东西。我想让它在保持坐标系的同时翻转我在y轴上制作的所有未来形状。这是我到目前为止所拥有的。
初始化:
const GLdouble XSize = 640, YSize = 480;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, XSize, YSize, 0, 1, 1000);
glMatrixMode(GL_MODELVIEW);
渲染:
float size = 30;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0, 0, -500);
glPushMatrix();
glTranslatef(size, size, 0.0f);
glBegin(GL_TRIANGLES);
glColor3f(0.1, 0.3, 0.8);
glVertex3f( 0.0f, size, 0.0f);
glVertex3f(-size,-size, 0.0f);
glVertex3f( size,-size, 0.0f);
glEnd();
glPopMatrix();
编辑:
我发现添加了 glScalef(1,-1,1); 会翻转我的形状,但我必须将它包含在我的形状的glPushMatrix()中,我不知道这是否是正确的方法,或者它是一个hackish解决方案。
答案 0 :(得分:1)
在这种情况下,您最好调整投影(将其视为“相机”)。
在这里查看tzaman的答案:Modifying OpenGL axis system
答案 1 :(得分:1)
要更改坐标系,需要按顺序进行缩放和翻译。
// Initialize OpenGL matrices
void init_gl() {
const float WIDTH = 640.0f;
const float HEIGHT = 480.0f;
const float HALF_WIDTH = WIDTH / 2.0f;
const float HALF_HEIGHT = HEIGHT / 2.0f;
// Setup the projection matrix
glMatrixMode(GL_PROECTION);
glLoadIDentity();
glOrtho(0, WIDTH, HEIGHT, 0.0f, 0.0f, 1000.0f);
// Setup the Allegro-to-view matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-HALF_WIDTH, HALF_HEIGHT, 0.0f);
glScalef(1.0f, -1.0f, 1.0f);
}
// Render scene
void render() {
// Now render using points in Allegro coordinates
const float size = 30.0f;
glBegin(GL_TRIANGLES);
glColor3f(0.1f, 0.3f, 0.8f);
glVertex3f( 0.0f, size, 0.0f);
glVertex3f(-size, -size, 0.0f);
glVertex3f( size, -size, 0.0f);
glEnd();
}
请注意,glTranslatef
位于glScalef
之前,因为转换矩阵在当前矩阵值的右侧相乘。此外,您不必每帧设置Allegro到视图矩阵;初始化期间一次就足以满足大多数用例。但是,您可以推送GL_MODELVIEW
并应用任何必要的模型转换。
以下是对其工作原理的概念分析。目标是允许图形程序员使用“Allegro”或所需坐标指定点,即原点位于正交投影左上角的坐标(在这种情况下,这与屏幕直接相关)。为此,您需要设置视图矩阵GL_MODELVIEW
,以便从这些所需坐标转换为正交相机坐标(也称为视图空间或眼睛空间)。
首先,您重新定位(缩放)所需坐标的y轴以匹配视图坐标(中间图)。其次,转换所需坐标的原点以匹配视图坐标的原点。这种平移是相对于视图坐标进行的(即视图坐标的原点是屏幕的一半水平向右,屏幕的一半垂直向下)。最后一步相当于转换相反方向的点。
符号上,比例将点P = (P.x, P.y)
转换为P' = (P.x, -P.y)
。翻译将点P'
转换为P'' = (P.x - w/2, P.y + h/2)
,其中w
是屏幕的宽度(480px),h
是高度(640px)。 (抱歉,最终的图表错误地切换了h
和w
P''
,因为我无法很好地处理图表。
请注意,z轴指向屏幕之外,因为我们没有将其缩放-1。
我更喜欢概念化坐标系变化的方式(更准确地说,当我们包含原点的概念时,框架的变化)是我们正在修改基础向量(x,y,等)和随后的缩放,旋转和平移操作的原点(按此顺序)。这与我们通过在相机移动的相反方向上应用平移来概念化移动相机的方式非常相似。
答案 2 :(得分:-1)
您应该阅读:http://www.opengl.org/documentation/specs/version2.0/glspec20.pdf 它非常明确地阐明了所有坐标变换。跟踪你的glVertex输入数据如何通过模型视图和投影,然后注意它是如何从那里成为标准化的窗口坐标和像素。这是一个阅读,你需要按照纸上的所有步骤来真正理解它。但这非常值得。