在 C++ 中的 OpenGL 中将坐标从 3D 透视投影映射到 2D 正交投影

Posted

技术标签:

【中文标题】在 C++ 中的 OpenGL 中将坐标从 3D 透视投影映射到 2D 正交投影【英文标题】:Mapping coordinates from 3D perspective projection to 2D orthographic projection in OpenGL in C++ 【发布时间】:2012-03-29 13:51:54 【问题描述】:

我用 C++ 编写了一个简单的 openGL 程序。该程序在 3D 透视投影中绘制一个球体,并尝试在 2D 正交投影中绘制一条连接球体中心和当前光标位置的线。现在为了画线,我不知道球心的坐标。

这是我的代码:

#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

void passive(int,int);
void reshape(int,int);
void init(void);
void display(void);
void camera(void);

int cursorX,cursorY,width,height;

int main (int argc,char **argv) 
    glutInit (&argc,argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
    glutInitWindowSize(1364,689);
    glutInitWindowPosition(0,0);
    glutCreateWindow("Sample");
    init();
    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutPassiveMotionFunc(passive);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return 0;
    

void display() 
    glClearColor (0.0,0.0,0.0,1.0);
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //  Render 3D content
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60,(GLfloat)width/(GLfloat)height,1.0,100.0);    // create 3D perspective projection matrix
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    camera();
    glTranslatef(-6,-2,0);
    glColor3f(1,0,0);
    glutSolidSphere(5,50,50);
    glPopMatrix();

    // Render 2D content
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, width,height, 0);                 // create 2D orthographic projection matrix
    glMatrixMode(GL_MODELVIEW);
    glColor3f(1,1,1);
    glBegin(GL_LINES);
        glVertex2f( centreX,centreY );          // coordinate of center of the sphere in orthographic projection
        glVertex2f( cursorX,cursorY );
    glEnd();

    glutSwapBuffers();
    

void camera(void) 
    glRotatef(0.0,1.0,0.0,0.0);
    glRotatef(0.0,0.0,1.0,0.0);
    glTranslated(0,0,-20);
    

void init(void) 
    glEnable (GL_DEPTH_TEST);
    glEnable (GL_BLEND);
    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_COLOR_MATERIAL);
    

void reshape(int w, int h) 
    width=w; height=h;
    

void passive(int x1,int y1) 
    cursorX=x1; cursorY=y1;

我无法确定 centerX 和 centerY 的值。无论如何我可以得到正确的值来画线?

【问题讨论】:

【参考方案1】:

您可能有兴趣使用 gluProject 之类的东西从您的对象坐标转到屏幕上的实际(投影)位置。一旦你有了对象的屏幕坐标,就很容易从一个点到另一个点画一条线。

在这种情况下,您需要投影球体的中心点。对于更复杂的对象,我发现投影对象边界框的所有角然后获取这些角的屏幕空间位置的范围是有意义的。

您应该在切换到正交投影(2D 模式)之前获得模型视图、视口和投影矩阵。

显然,为了从屏幕位置(例如,您在窗口中单击的位置)转到世界位置,您需要使用它的配套函数 gluUnProject

注意gluProject出来的坐标不一定直接对应窗口位置;您可能需要翻转“Y”坐标。

查看this GDSE discussion,了解有关如何解决问题的其他一些想法。

【讨论】:

gluProject() 似乎返回了一些大的随机值。 centerX、centerY 和 centerZ 的值不在窗口范围内。我的代码在:pastebin.com/1p7gNS3i :gluProject() 似乎返回了一些大的随机值。 centerX、centerY 和 centerZ 的值不在窗口范围内。我的代码位于:pastebin.com/1p7gNS3i 我可以看到的一个问题是,您推送模型视图矩阵,然后应用相机变换,然后渲染您的对象,然后弹出模型视图矩阵(将其恢复为身份),然后查询您的模型视图矩阵。设置好相机后查询模型视图矩阵。

以上是关于在 C++ 中的 OpenGL 中将坐标从 3D 透视投影映射到 2D 正交投影的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL获取像素的原始3d坐标

OpenGL工作流程

找不到使用 C# 在 openGL 中将纹理应用于 3d 对象的方法

OpenGL中的坐标系

统一D3D与OpenGL坐标系统

如何从 3d 对象文件中获取 3d 坐标。