反转y轴,并在OpenGL中设置坐标系

发布于 2024-11-06 11:30:36 字数 931 浏览 0 评论 0原文

在 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() 中,并且我不知道这是否是执行此操作的正确方法,或者它是否是一个黑客解决方案。

In OpenGL, I am trying to invert the y axis, and set a specific type of coordinate system just like how Allegro has it. Assuming my window is 640x480, I want the top left of the screen be axis (0, 0), and the bottom right (640, 480). So far, I managed to get the proper coordinate system I want, but I don't know if it is done the proper way. As for flipping the y axis, I was unable to invert it without modifying the coordinate system I currently have. I don't want something hackish only to flip 1 shape. I want it to flip all future shapes I make on the y axis while maintaining the coordinate system. Here is what I have so far.

Initialize:

const GLdouble XSize = 640, YSize = 480;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, XSize, YSize, 0, 1, 1000);
glMatrixMode(GL_MODELVIEW);

Render:

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();

Edit:

I figured out that adding
glScalef(1, -1, 1);
will flip my shape, but I have to include it inside glPushMatrix() of my shapes, and I don't know if this is the proper way to do this or if its a hackish solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

明明#如月 2024-11-13 11:30:36

在这种情况下,你最好调整投影(将其视为“相机”)。

在这里查看 tzaman 的答案:修改 OpenGL 轴系统

You'd be better off tweaking the projection (think of it as the "camera") in that case.

Check out tzaman's answer here: Modifying OpenGL axis system

一萌ing 2024-11-13 11:30:36

要更改坐标系,需要按顺序进行缩放和平移。

// 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-to-view 矩阵;对于大多数用例来说,初始化期间一次就足够了。但是,您可以推送 GL_MODELVIEW 并应用任何必要的模型转换。


以下是其工作原理的概念分析。目标是允许图形程序员使用“Allegro”或所需坐标指定点,即原点位于正交投影左上角的坐标(在本例中,这直接与屏幕相关)。为了实现这一点,您需要设置视图矩阵 GL_MODELVIEW 来从这些所需的坐标转换为正交相机坐标(也称为视图空间或眼睛空间)。

首先,重新定向(缩放)所需坐标的 y 轴以匹配视图坐标(中图)。其次,平移所需坐标的原点以匹配视图坐标的原点。这种平移是相对于视图坐标进行的(即视图坐标的原点是水平向右的一半屏幕和垂直向下的一半屏幕)。最后一步相当于在平移的相反方向上变换点。

象征性地,比例将点 P = (Px, Py) 转换为 P' = (Px, -Py)。转换将点 P' 转换为 P'' = (Px - w/2, Py + h/2),其中 w 是屏幕的宽度 (480px) 和 h 是高度 (640px)。 (抱歉,最终的图表错误地将 hw 切换为 P'',因为我不能很好地绘制图表)。

请注意,z 轴指向屏幕外,因为我们没有将其缩放 -1。

我更喜欢概念化坐标系变化的方式(更准确地说,当我们包含原点概念时框架的变化)是我们修改基向量(x,y等)以及原点以及随后的缩放、旋转和平移操作(按该顺序)。这与我们通过在相机移动的相反方向应用平移来概念化移动相机的方式非常相似。

粗略绘制两种转换的图表

To change the coordinate system, a scale and a translate are required in that order.

// 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();
}

Note that glTranslatef comes before glScalef because transformation matrices are multiplied on the right side of the current matrix value. Also, you do not have to set the Allegro-to-view matrix per frame; once during initialization is enough for most use cases. You might, however, push GL_MODELVIEW and apply any model transforms that are necessary.


Here is a conceptual analysis of how this works. The goal is to allow you, the graphics programmer, to specify points using 'Allegro' or desired coordinates, i.e. coordinates where the origin is top-left corner of the orthographic projection (in this case, this relates directly to the screen). To accomplish this, you setup the view matrix GL_MODELVIEW to transform from these desired coordinates to orthographic camera coordinates (also known as view space or eye space).

First, you reorient (scale) the y-axis of desired coordinates to match view coordinates (middle figure). Second, you translate the origin of desired coordinates to match the origin of view coordinates. This translation is made relative to view coordinates (i.e. the origin of view coordinates is half the screen horizontally to the right and half the screen vertically down). This last step is equivalent to transforming points in the opposite direction of the shift.

Symbolically, the scale transforms the point P = (P.x, P.y) to P' = (P.x, -P.y). The translate transforms the point P' to P'' = (P.x - w/2, P.y + h/2) where w is the width of the screen (480px) and h is the height (640px). (Sorry, the final diagram incorrectly switches h and w for P'' because I can't do diagrams on SO very well).

Note that the z-axis points out of the screen since we did not scale it by -1.

The way I prefer to conceptualize changes of coordinate systems (more accurately, change of frames when we include the concept of an origin) is that we're modifying the basis vectors (x, y, etc.) and the origin with subsequent scale, rotation, and translation operations (in that order). This is very similar to the way we conceptualize moving the camera around by applying translations in the opposite direction with which the camera is moving.

Roughly drawn diagram of the two transformations

如果没有 2024-11-13 11:30:36

您应该阅读: http://www.opengl.org/documentation/specs /version2.0/glspec20.pdf
它非常明确地阐明了所有坐标变换。关注 glVertex 输入数据如何通过模型视图和投影,然后注意它如何从那里变成标准化的窗口坐标和像素。这是一本相当值得阅读的书,您需要遵循纸上的所有步骤才能真正理解它。但这是非常值得的。

You should read: http://www.opengl.org/documentation/specs/version2.0/glspec20.pdf
It very explicitly spells out all coordinate transforms. Follow how your glVertex input data goes through model-view and projection, then pay attention to how it becomes normalized window coordinates and pixels from there. It is quite a read and you need to follow all the steps on paper to really understand it. But it will be well worth it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文