Страницы

Поиск по вопросам

суббота, 11 января 2020 г.

Как сохранить пропорции 2D объекта в окне рендера OpenGL?

#cpp #opengl


Есть круг.  



Но если изменить размеры окна(ресайз) например вот так:



или так:  



То получается овал.

Вопрос: как сделать, чтобы при ресайзе, круг всегда оставался кругом?

Код:

#include "stdafx.h"
#include 
#include 

/* подключаем библиотеку GLUT */
#include 

static GLfloat spin = 0.0;


void init(void)
{   
    //glClearColor() устанавливает черный цвет фона
    glClearColor(0.0, 0.0, 0.0, 0.0);
    //glShadeModel(GL_FLAT);////Режим без сглаживания
    glShadeModel(GL_SMOOTH); //Сглаживание. По умолчанию установлен режим GL_SMOOTH.

}

void display(void)
{
    // glClear() очищает фон .
    //В дальнейшем, всякий раз, когда  glClear() будет вызываться,
    //она будет очищать окно в черный цвет .
    glClear(GL_COLOR_BUFFER_BIT);
    glPushMatrix();
    //glRotatef(Angle,Xtrue,Ytrue,Ztrue) отвечает за вращения объекта вдоль
    glRotatef(spin, 0.0, 0.0, 1.0);

    //glColor3f() устанавливает цвет прорисовки - белый цвет.
    glColor3f(1.0, 1.0, 1.0);
    //glColor3f(1.0, 0.0, 0.0);//-красный.

    #define PI 3.1415926535898
    GLint circle_points = 25;
    //glBegin() и glEnd() определяют обьект, который будет прорисован .
    glBegin(GL_LINE_LOOP);
    for (int i = 0; i < circle_points; i++) {
        double angle = 2 * PI*i / circle_points;
        //glVertex2f() определяет вершины полигона, в качестве параметров - 2 координаты
x, y.
        glVertex2f(cos(angle), sin(angle));
    }
    glEnd();


    glBegin(GL_LINE_LOOP);
    for (int i = 0; i < circle_points; i++) {
        double angle = 6 * PI*i / circle_points;
        glVertex2f(cos(angle), sin(angle));
    }
    glEnd();

    glBegin(GL_LINE_LOOP);
    for (int i = 0; i < circle_points; i++) {
        double angle = 20 * PI*i / circle_points;
        glVertex2f(cos(angle), sin(angle));
    }
    glEnd();

    glPopMatrix();
    /*glutSwapBuffers(), делающий свопинг буффера .
    Имеется 2 буффера, и пока на экран не выводится полностью один из них,
    второй остается полностью за кадром, и не произойдет наложения одного надругой .*/
    glutSwapBuffers();
}

void spinDisplay(void)
{
    spin = spin + 0.05;
    if (spin > 360.0)
        spin = spin - 360.0;
    glutPostRedisplay();
}

void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    //glOrtho() определяет координатную систему .
    glOrtho(-2.0, 2.0, -2.0, 2.0, -1.0, 1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void mouse(int button, int state, int x, int y)
{
    switch (button) {
    case GLUT_LEFT_BUTTON:
        if (state == GLUT_DOWN)
            glutIdleFunc(spinDisplay);
        break;
    case GLUT_MIDDLE_BUTTON:
        if (state == GLUT_DOWN)
            glutIdleFunc(NULL);
        break;
    default:
        break;
    }
}

/*
* double buffer display mode.
* Register mouse input callback functions
*/
int main(int argc, char** argv)
{
    // glutInit(int *argc, char **argv) - самая первая команда инициализации
    glutInit(&argc, argv);
    //glutInitDisplayMode(unsigned int mode) - устанавливает цветовую модель - RGBA
или color - index .
    //Например, glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH) -
    //устанавливает  двойной буфер, цветовую модель RGB .
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    //glutInitWindowSize(int width, int size) - размер окна
    glutInitWindowSize(250, 250);
    //glutInitWindowPosition(int x, int y) - установливает начало координат окна.
    glutInitWindowPosition(100, 100);
    //int glutCreateWindow() - создает окно
    glutCreateWindow(argv[0]);
    init();
    //glutDisplayFunc() - вызывается всякий раз при перерисовке окна .
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    //glutMainLoop(void) - эта функция вызывается после всех остальных .
    glutMainLoop();
    return 0;
}


UPDATE:

Добавил -

void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    double aspect = (double)w / h;
    //glOrtho() определяет координатную систему .
    glOrtho(-2.0 * aspect, 2.0 * aspect, -2.0, 2.0, -1.0, 1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}


Итого всё в порядке,но...

Так хорошо.



Так не хорошо.


    


Ответы

Ответ 1



Вам нужно сделать изменение ширины/высоты в glOrtho при изменении размеров окна, чтобы сохранялись пропорции отрисовки. Попробуйте так: double ww = w, hh = h; if (w > h) glOrtho(-2.0 * (ww/hh), 2.0 * (ww/hh), -2.0, 2.0, -1.0, 1.0); else glOrtho(-2.0, 2.0, -2.0 * (hh/ww), 2.0 * (hh/ww), -1.0, 1.0); В книгах по OpenGL часто такой приём используется.

Комментариев нет:

Отправить комментарий