본문 바로가기

기타/컴퓨터 그래픽스 & OpenGL

[OpenGL] 메뉴 콜백 / 2022.10.23

* 출처 : OpenGL로 배우는 3차원 컴퓨터 그래픽스, 한빛아카데미

1. 콜백 함수를 사용하여 메뉴를 만드는 방법을 알아보자.

#include <glut.h>
#include <gl/GL.h>
#include <gl/GLU.h>

GLboolean IsSphere = true;

void MyDisplay() {
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(0.5, 0.0, 0.5);
    if (IsSphere) // IsSphere가 true라면
        glutWireSphere(0.2, 15, 15); //원구를 그림
    else // false라면
        glutWireTorus(0.1, 0.3, 40, 20); // 원환체를 그림
    glFlush();
}

void MyMainMenu(int entryID) { 
    if (entryID == 1)
        IsSphere = true;
    else if (entryID == 2)
        IsSphere = false;
    else if (entryID == 3)
        exit(0);
    glutPostRedisplay();
}

int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB);
    glutInitWindowSize(300, 300);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("OpenGL Example Drawing");

    glClearColor(1.0, 1.0, 1.0, 1.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
    // 새로운 메뉴 만들기
    GLint MyMainMenuID = glutCreateMenu(MyMainMenu);
    // 메뉴 항목 (메뉴 이름, 번호)
    glutAddMenuEntry("Draw Sphere", 1);
    glutAddMenuEntry("Draw Torus", 2);
    glutAddMenuEntry("Exit", 3);
    // 오른쪽 마우스 버튼을 누를 때 메뉴 팝업
    glutAttachMenu(GLUT_RIGHT_BUTTON);
    glutDisplayFunc(MyDisplay);
    glutMainLoop();
    return 0;
}

- 그림은 3개의 메뉴 항목으로 구성된다. Draw Sphere는 원구를 , Draw Torus는 원환체를, Exit는 프로그램을 종료하기 위한 메뉴이다.

 

1-1) Main()

- glutCreateMenu() : 새로운 메뉴 생성, 함수 실행 결과가 좌변의 변수에 할당됨

- glutAddMenuEntry() : 메뉴 항목 생성 -> 파라미터 (메뉴 이름, 번호)

- glutAttachMenu(GLUT_RIGHT_BUTTON) : 오른쪽 마우스 버튼을 누를 때 메뉴 팝업

 

1-2) MyMainMenu()

-  사용자가 Draw Sphere를 누르면 파라미터 1이 전달되고 그 결과 전역변수 IsSphere 값이 true가 된다

- 만약 Draw Torus를 누르면 파라미터 2가 전달되고 전역변수 값이 false가 된다.

- 이 전역변수 값 true or false가 MyDisplay()에서 어떤 모델로 그릴 것인지를 결정한다.

결과

2. 계단식 메뉴

위의 코드에 서브 메뉴 항목을 추가해 보자

 

#include <glut.h>
#include <gl/GL.h>
#include <gl/GLU.h>

GLboolean IsSphere = true;
GLboolean IsSmall = true;

void MyDisplay() {
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(0.5, 0.0, 0.5);
    if ((IsSphere) && (IsSmall)) // 작은 원구
        glutWireSphere(0.2, 15, 15);       
    else if ((IsSphere) && (!IsSmall)) // 큰 원구
        glutWireSphere(0.4, 15, 15);       
    else if ((!IsSphere) && (IsSmall))
        glutWireTorus(0.1, 0.3, 40, 20);  // 작은 원환체
    else
        glutWireTorus(0.2, 0.5, 40, 20);  // 큰 원환체
    glFlush();
}

void MyMainMenu(int entryID) {
    if (entryID == 1)
        IsSphere = true;                
    else if (entryID == 2)
        IsSphere = false;              
    else if (entryID == 3)
        exit(0);                       
    glutPostRedisplay();
}

void MySubMenu(int entryID) {
    if (entryID == 1)
        IsSmall = true;                 
    else if (entryID == 2)
        IsSmall = false;                
    glutPostRedisplay();
}

int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB);
    glutInitWindowSize(300, 300);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("OpenGL Example Drawing");

    glClearColor(1.0, 1.0, 1.0, 1.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);

    GLint MySubMenuID = glutCreateMenu(MySubMenu); // 서브 메뉴 생성
    glutAddMenuEntry("Small One", 1);
    glutAddMenuEntry("Big One", 2);
    GLint MyMainMenuID = glutCreateMenu(MyMainMenu);
    glutAddMenuEntry("Draw Sphere", 1);
    glutAddMenuEntry("Draw Torus", 2);
    // Change Size라는 서브 메뉴 추가
    glutAddSubMenu("Change Size", MySubMenuID);
    glutAddMenuEntry("Exit", 3);
    glutAttachMenu(GLUT_RIGHT_BUTTON);
    glutDisplayFunc(MyDisplay);
    glutMainLoop();
    return 0;
}

- 기존의 메뉴 항목에 Change Size라는 서브메뉴를 하나 추가한다

- 서브 메뉴는 사이즈를 조절하는 메뉴로 전역 변수 IsSmall을 사용한다

- 진행 방식은 위의 코드와 동일하다