【问题标题】:Using gluUnProject() to draw a quad at the cursor position使用 gluUnProject() 在光标位置绘制四边形
【发布时间】:2011-05-07 07:03:57
【问题描述】:

我在 OpenGL 中使用 SDL,到目前为止,我已经完成了 2d 中的所有操作(使用 glOrtho())

现在我想尝试在 3D 中绘制东西,但当然,因为我现在已经将第 3 维加入到混合物中,所以事情变得更加复杂。

我想要做的是,获取光标的屏幕坐标,将它们转换为(?)世界坐标(我可以在 OpenGL 中使用的坐标,因为我现在有透视等),然后绘制该位置的四边形(鼠标光标位于四边形的中心)

我已经阅读了一些关于 gluUnProject() 的教程,并且我有点明白我应该做什么,但是由于我是自学的,所以很容易感到困惑并且无法正确理解我在做什么。

因此,我主要是从我找到的示例中复制的。

下面是我的代码(我拿出了错误检查等,试图减少一点)

如您所见,我有 mouseX、mouseY 和 mouseZ 变量,其中 mouseX 和 mouseY 从 SDL 中获取值。

我尝试使用 glReadPixel() 来获取 mouseZ,但我不确定我是否做得对。

问题是当我点击时,四边形没有绘制在正确的位置(我猜部分是因为我不知道如何正确获取 mouseZ,所以我只是在 gluUnProject() 中将其替换为1.0?)

我在 glTranslatef() 函数中使用了新的坐标 (wx, wy, wz) 但又一次因为我不知道如何正确获取 mouseZ 我猜这是它不起作用的原因适当地。 如果我将 wz 替换为 -499,它似乎可以正常工作,但我需要知道如何在不手动找到正确(或几乎正确)数字的情况下获得准确的结果

如果有人能告诉我我做错了什么,或者给我任何建议,将不胜感激。

#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>

SDL_Surface* screen = 0;
SDL_Event event;
bool isRunning = true;

int mouseX, mouseY, mouseZ = 0;

GLint viewport[4];
GLdouble mvmatrix[16], projmatrix[16];
GLint realY; /* OpenGL y coordinate position */
GLdouble wx, wy, wz; /* returned world x, y, z coords */

int main(int argc, char **argv) {
    SDL_Init(SDL_INIT_EVERYTHING);

    screen = SDL_SetVideoMode(800, 600, 32, SDL_OPENGL);

    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);

    glViewport(0, 0, 800, 600);

    glClearDepth(1.f);
    glClearColor(0, 0, 0, 0);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluPerspective(90.f, 1.f, 1.f, 500.f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    while(isRunning) {
        while(SDL_PollEvent(&event)) {
            if(event.type == SDL_QUIT) {
                isRunning = false;
            }

            if(event.type == SDL_MOUSEBUTTONDOWN) {
                if(event.button.button == SDL_BUTTON_LEFT) {
                    SDL_GetMouseState(&mouseX, &mouseY);

                    glGetIntegerv(GL_VIEWPORT, viewport);
                    glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
                    glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
                    realY = viewport[3] - (GLint) mouseY - 1;
                    glReadPixels(mouseX, realY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &mouseZ);

                    gluUnProject((GLdouble)mouseX, (GLdouble)realY, 1.0, mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
                }
            }
        }

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glPushMatrix();

        glTranslatef(wx, wy, wz);

        glBegin(GL_QUADS);
            glColor4f(1.f, 0.f, 0.f, 1.f);
            glVertex3f(-20.f, -20.f, 0.f);

            glColor4f(0.f, 1.f, 0.f, 1.f);
            glVertex3f(-20.f, 20.f, 0.f);

            glColor4f(0.f, 0.f, 1.f, 1.f);
            glVertex3f(20.f, 20.f, 0.f);

            glColor4f(1.f, 0.f, 1.f, 1.f);
            glVertex3f(20.f, -20.f, 0.f);
        glEnd();

        glPopMatrix();

        SDL_GL_SwapBuffers();
    }

    SDL_FreeSurface(screen);

    return 0;
}

【问题讨论】:

    标签: opengl screen coordinates sdl translate


    【解决方案1】:

    我发现如果我添加以下内容:

    GLfloat depth[2];
    

    然后将 glReadPixels() 更改为:

    glReadPixels(mouseX, realY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &mouseZ);
    

    到:

    glReadPixels(mouseX, realY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, depth);
    

    然后我只是将 gluUnProject() 从:

    gluUnProject((GLdouble)mouseX, (GLdouble)realY, mouseZ, mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
    

    到:

    gluUnProject((GLdouble) mouseX, (GLdouble) realY, depth[0], mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
    

    然后我可以得到我想要的 Z 值。

    然后我只是为 wz 添加了一个小值,例如:wz += 1; 以确保四边形出现在我单击的位置上方,并且它似乎可以按我现在的预期工作。

    【讨论】:

      【解决方案2】:

      要猜测一个 Z,你需要知道这个 z 的含义:

      通常的意思是你想将对应的线(相机原点,像素)与一个3d对象相交。您可以为此使用 Z 缓冲区。

      如果不是(您想将多边形粘贴到没有 3D 关系的光标上),只需使用 2D 功能,您可以在同一帧中绘制时在 3D 和 2D 投影之间交替(使用投影矩阵或使用2D 特定功能),因此您不需要 z。

      如果在您的设计中没有任何理由,则为 Z 设置默认值是个坏主意。

      只有一个 Z 值可以为您提供正确的像素坐标。

      openGL 中 2D 和 3D 坐标之间的联系是 OpenGL 在 Z = 1 处使用投影平面。 然后将像素坐标从 [-1,1] 缩放到像素坐标。

      【讨论】:

      • 所以,为了检查我的理解,如果我想找到正确的 Z 值,我首先需要某种我想放置四边形的表面?
      • 对于第一个选项是,如果您希望该四边形位于 3D 空间中。如果您似乎没有任何物体,则可以使用与相机方向正交的投影平面。正如您所说,这就是您在使用固定 Z 时所做的事情。但是你必须找到正确的 Z 来匹配像素坐标。这取决于您的投影矩阵。所以我认为将投影矩阵切换为 2D 来绘制四边形会更容易。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多