使用OpenGL实现真正的等轴投影

18

有没有一种简单的方法可以实现等轴投影?

我的意思是真正的等轴投影,而不是一般的正交投影。

(等轴投影只在单位X、Y和Z向量的投影长度相等且它们之间的角度恰好为120度时发生。)


请仅返回翻译后的文本:重复的http://www.allegro.cc/forums/thread/600737 - aib
4个回答

28

尝试使用gluLookAt

glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

/* use this length so that camera is 1 unit away from origin */
double dist = sqrt(1 / 3.0);

gluLookAt(dist, dist, dist,  /* position of camera */
          0.0,  0.0,  0.0,   /* where camera is pointing at */
          0.0,  1.0,  0.0);  /* which direction is up */
glMatrixMode(GL_MODELVIEW);

glBegin(GL_LINES);

glColor3d(1.0, 0.0, 0.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(1.0, 0.0, 0.0);

glColor3d(0.0, 1.0, 0.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(0.0, 1.0, 0.0);

glColor3d(0.0, 0.0, 1.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(0.0, 0.0, 1.0);

glEnd();

glFlush();

效果如下

alt text

我们可以画一个立方体来检验平行线确实是平行的。

glPushMatrix();
glTranslated(0.5, 0.5, 0.5);
glColor3d(0.5, 0.5, 0.5);
glutWireCube(1);
glPopMatrix();

alt text


这不会给你等距投影,因为平行线,比如沿着x和y轴的线,看起来不是平行的,而实际上它们应该是平行的。 - Jesse Beder
1
看一下问题中链接的维基百科文章中的图片,它看起来与该投影完全相同。任何平行线都会呈现为平行线,因为这是正交投影(http://en.wikipedia.org/wiki/Orthographic_projection)。X轴和Y轴不是平行的。 - cobbal
我并不是说x轴和y轴是平行的,而是在等距投影中,与x轴平行的线应该呈现出平行的形状(而我认为在你的投影中不会),同样地,在y方向上也是如此。 - Jesse Beder
1
哎呀,我的错。我没注意到您只调用了gluLookAt。现在加1分。 - Jesse Beder

9

等轴测投影只是使用具有特定旋转角度的正交投影的问题。

您应该能够选择8个潜在方向中的任何一个,使用正交投影获得模型的完美等轴测视图。只需按照您参考的维基文章中的数学设置视图矩阵,并对投影矩阵进行正交投影,即可完成所有设置。


3
也许我没有完全理解数学,但是按照维基百科的链接所述,您不可以将相机定位并使用标准正交投影吗?
即使不同,投影堆栈完全由您决定。
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// your isometric matrix here (see math on Wikipedia)
glMatrixMode(GL_MODELVIEW);

2

如果您不想使用GLU,这里是使用glOrtho的基本方法。

void gl_enter_2_5d_mode (void)
{
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();

    glLoadIdentity();

    double scale = 50;
    glOrtho(-scale,
            scale,
            -scale * 0.7,
            scale * 0.7,
            -scale,
            scale);

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();

    glLoadIdentity();

    glRotatef(35.264f, 1.0f, 0.0f, 0.0f);
    glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
}

void gl_leave_2_5d_mode (void)
{
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
}

then draw a cube in it

void cube (double size)
{
    glBegin(GL_QUADS);

    glVertex3f(size,size,size);
    glVertex3f(-size,size,size);
    glVertex3f(-size,-size,size);
    glVertex3f(size,-size,size);

    glVertex3f(size,size,-size);
    glVertex3f(-size,size,-size);
    glVertex3f(-size,-size,-size);
    glVertex3f(size,-size,-size);

    glVertex3f(size,size,size);
    glVertex3f(size,-size,size);
    glVertex3f(size,-size,-size);
    glVertex3f(size,size,-size);

    glVertex3f(-size,size,size);
    glVertex3f(-size,-size,size);
    glVertex3f(-size,-size,-size);
    glVertex3f(-size,size,-size);

    glVertex3f(size,size,size);
    glVertex3f(-size,size,size);
    glVertex3f(-size,size,-size);
    glVertex3f(size,size,-size);

    glVertex3f(size,-size,size);
    glVertex3f(-size,-size,size);
    glVertex3f(-size,-size,-size);
    glVertex3f(size,-size,-size);

    glEnd();
}

void test (void)
{
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glBindTexture(GL_TEXTURE_2D, 0);
    cube(1.0);
    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
}

并调用类似以下的内容

gl_enter_2_5d_mode()
test()
gl_leave_2_5d_mode()

如果您想在2D和2.5D之间切换(以便绘制用户界面),那么我有类似的功能来进入和离开2D模式,例如:

void gl_init_2d_mode (void)
{
    /*
     * Enable Texture Mapping
     */
    glEnable(GL_TEXTURE_2D);

    /*
     * Enable alpha blending for sprites
     */
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    /*
     * Setup our viewport
     */
    glViewport(0, 0, game.video_pix_width,
               game.video_pix_height);

    /*
     * Make sure we're changing the model view and not the projection
     */
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();

    /*
     * Reset the view
     */
    glLoadIdentity();

    gl_init_fbo();
}

void gl_enter_2d_mode (void)
{
    /*
     * Change to the projection matrix and set our viewing volume.
     */
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();

    /*
     * Reset the view
     */
    glLoadIdentity();

    /*
     * 2D projection
     */
    glOrtho(0,
             game.video_gl_width, game.video_gl_height,
             0, -1200.0, 1200.0);

    /*
     * Make sure we're changing the model view and not the projection
     */
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();

    /*
     * Reset the view
     */
    glLoadIdentity();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接