настоящая изометрическая проекция с opengl

Я новичок в программировании OpenGL с C++ и не очень хорошо разбираюсь в математике. Есть ли простой способ получить изометрическую проекцию?

Я имею в виду истинную изометрическую проекцию, а не общую ортогональную проекцию.

(Изометрическая проекция происходит только тогда, когда проекции единичных векторов X, Y и Z имеют одинаковую длину, а углы между ними составляют ровно 120 градусов.)

Фрагменты кода высоко ценятся.


person someone    schedule 29.06.2009    source источник
comment
дубликат allegro.cc/forums/thread/600737   -  person aib    schedule 01.07.2009


Ответы (4)


Попробуйте использовать 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();

Результаты в

альтернативный текст

Мы можем нарисовать куб, чтобы проверить, что параллельные линии действительно параллельны.

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

альтернативный текст

person cobbal    schedule 29.06.2009
comment
Это не даст вам изометрическую проекцию, потому что параллельные линии, скажем, вдоль осей x и y, не будут казаться параллельными, хотя на самом деле должны. - person Jesse Beder; 29.06.2009
comment
посмотрите на картинку в статье в Википедии, на которую тоже была ссылка в вопросе, она выглядит точно так же, как эта проекция. Любые параллельные линии будут казаться параллельными, потому что это орфографическая проекция (en.wikipedia.org/wiki/Orthographic_projection). Оси x и y не параллельны. - person cobbal; 29.06.2009
comment
Я не имею в виду, что оси x и y параллельны, но линии, параллельные оси x, должны казаться параллельными в изометрической проекции (и я не думаю, что они будут в вашей) и аналогичным образом в направлении y. - person Jesse Beder; 29.06.2009
comment
Ой, мой плохой. Я пропустил, что ты только звонил gluLookAt. +1 сейчас. - person Jesse Beder; 30.06.2009

Изометрическая проекция — это всего лишь вопрос использования ортогональной проекции с определенным углом поворота.

Вы должны иметь возможность выбрать любую из 8 возможных ориентаций с ортогональной проекцией и получить идеальный изометрический вид вашей модели. Просто следуйте математике в упомянутой вами статье Wiki для настройки матрицы представления и сделайте орфографическую проекцию для вашей матрицы проекции, и все готово.

person Reed Copsey    schedule 29.06.2009

Может быть, я не совсем правильно понимаю математику, но не могли бы вы просто расположить камеру, как это объясняется в этой ссылке в Википедии, и использовать стандартную ортогональную проекцию?

Даже если это не одно и то же, стек проекций полностью зависит от вас.

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// your isometric matrix here (see math on Wikipedia)
glMatrixMode(GL_MODELVIEW);
person Bob Somers    schedule 29.06.2009

Если вы не хотите использовать GLU, вот голые кости, использующие glOrtho

void gl_enter
gl_enter_2_5d_mode()
test()
gl_leave_2_5d_mode()
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
gl_enter_2_5d_mode()
test()
gl_leave_2_5d_mode()
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();
}
person Neil McGill    schedule 27.03.2017