본문 바로가기
전공/컴퓨터 그래픽스

OpenGL 기본틀 : Callback 프로그래밍 (1)Reshape Callback, Keyboard Callback, Mouse Callback

by 임 낭 만 2023. 4. 10.

Reshape Callback

#include <GL/freeglut.h>

void MyDisplay() {	//사각형을 그리기 위한 함수
    glClear(GL_COLOR_BUFFER_BIT);       //컬러버퍼에 초기화 색을 가함
    glColor3f(0.5, 0.5, 0.5);           //그리는 도형의 색상 설정 : 회색 (R,G,B가 같으면 회색)
    glBegin(GL_POLYGON);                //도형을 그리기 위한 시작 지점 설정, 사각형 그리기
        glVertex3f(-0.5, -0.5, 0.0);    //좌하단 좌표 (첫 번째 꼭짓점)
        glVertex3f(0.5, -0.5, 0.0);     //우하단 좌표 (두 번째 꼭짓점)
        glVertex3f(0.5, 0.5, 0.0);      //우상단 좌표 (세 번째 꼭짓점)
        glVertex3f(-0.5, 0.5, 0.0);     //좌상단 좌표 (네 번째 꼭짓점)
    glEnd();		//도형 그리기 종료
    glFlush();		//명령어 버퍼에 쌓인 명령어 실행
}
void MyReshape(int NewWidth, int NewHeight) {
    glViewport(0, 0, NewWidth, NewHeight);	//뷰포트 설정 (0, 0)부터 시작하기
    GLfloat WidthFactor = (GLfloat) NewWidth / (GLfloat) 300;
    GLfloat HeightFactor = (GLfloat) NewHeight / (GLfloat) 300;
    //새로운 창의 크기를 기존의 300x300 크기로부터 얼마나 변화했는지 계산
    glMatrixMode(GL_PROJECTION);		//행렬 모드를 GL_PROJECTION으로 설정
    glLoadIdentity();				//현재의 행렬 상태 초기화함.
    glOrtho(-1.0 * WidthFactor, 1.0 * WidthFactor,
        -1.0 * HeightFactor, 1.0 * HeightFactor, -1.0, 1.0);
    //직교 좌표계를 설정하기 위해 사용됨. x축과 y축의 범위를 -widthfactor부터 widthfactor까지
    //-heightfactor부터 heightfactor까지로 설정하고, z축의 범위는 -1부터 1까지로 설정
}
int main(int argc, char** argv) {
    glutInit(&argc,argv);			//GLUT 라이브러리를 초기화함
    glutInitDisplayMode(GLUT_RGB);		//디스플레이 모드를 RGB 컬러 모드로 설정함
    glutInitWindowSize(300, 300);		//윈도우 크기 설정
    glutInitWindowPosition(0, 0);		//윈도우 위치 설정
    glutCreateWindow("OpenGL Example Drawing"); //윈도우 생성
    glClearColor(1.0, 1.0, 1.0, 1.0);   	//초기화 색은 백색
    glutDisplayFunc(MyDisplay);			//디스플레이 콜백 함수 등록
    glutReshapeFunc(MyReshape);			//리셰이프 콜백 함수 등록
    glutMainLoop();				//이벤트 루프 실행
    return 0;
}

더보기

glMatrixMode()는 투상 행렬을 변환대상으로 설정하라는 명령이며, glLoadIdentity()는 이 행렬에 일단 항등 행렬을 실으라는 명령어. 이 두 명령이 선행되어야 glOrtho() 함수에서 지정한 값이 해당 행렬에 곱해진다.

가시부피 = 화면에 보이고자 하는 물체의 범위를 말한다. 

가시 부피를 정의하기 위한 glOrtho() 함수의 프로토타입은 다음과 같다. 

void glOrtho(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far);

 

투상 방식에서 투상면은 가시 부피의 전방 절단면과 동일. glOrtho()에 의해 가시 부피의 모습을 조절함으로써 왜곡 해소 가능. → 투상면 자체의 종횡비가 뷰 포트의 종횡비가 일치해서 물체는 전혀 왜곡되지 않는다. 


Keyboard Callback

#include <GL/freeglut.h>

void MyDisplay() {	//사각형을 그리기 위한 함수
    glClear(GL_COLOR_BUFFER_BIT);       //컬러버퍼에 초기화 색을 가함
    glColor3f(0.5, 0.5, 0.5);           //그리는 도형의 색상 설정 : 회색 (R,G,B가 같으면 회색)
    glBegin(GL_POLYGON);                //도형을 그리기 위한 시작 지점 설정, 사각형 그리기
        glVertex3f(-0.5, -0.5, 0.0);    //좌하단 좌표 (첫 번째 꼭짓점)
        glVertex3f(0.5, -0.5, 0.0);     //우하단 좌표 (두 번째 꼭짓점)
        glVertex3f(0.5, 0.5, 0.0);      //우상단 좌표 (세 번째 꼭짓점)
        glVertex3f(-0.5, 0.5, 0.0);     //좌상단 좌표 (네 번째 꼭짓점)
    glEnd();		//도형 그리기 종료
    glFlush();		//명령어 버퍼에 쌓인 명령어 실행
}
void MyKeyboard(unsigned char KeyPressed, int X, int Y) {
//매개변수는 눌려진 키의 아스키 코드 값, 마우스의 현재 좌표인 x, y 값 전달됨
    switch (KeyPressed){	//'q', 'Q', 혹은 ESC 키를 누르면 프로그램 종료
    case 'Q':
        exit(0); break;
    case 'q':
        exit(0); break;
    case 27:                //'esc' 키의 아스키 코드 값
        exit(0); break;
    }
}
int main(int argc, char** argv) {
    glutInit(&argc,argv);			//GLUT 라이브러리를 초기화함
    glutInitDisplayMode(GLUT_RGB);		//디스플레이 모드를 RGB 컬러 모드로 설정함
    glutInitWindowSize(300, 300);		//윈도우 크기 설정
    glutInitWindowPosition(0, 0);		//윈도우 위치 설정
    glutCreateWindow("OpenGL Drawing Example");	//윈도우 생성
    glClearColor(1.0, 1.0, 1.0, 1.0);		//초기화 색은 백색
    glMatrixMode(GL_PROJECTION);		//행렬 모드를 GL_PROJECTION으로 설정
    glLoadIdentity();				//현재의 행렬 상태 초기화함.
    glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);	//뷰포트의 좌표계 설정
    glutDisplayFunc(MyDisplay);			//디스플레이 콜백 함수 등록
    glutKeyboardFunc(MyKeyboard);		//키보드 콜백 함수 등록
    glutMainLoop();				//이벤트 루프 실행
    return 0;
}

Mouse Callback

#include <GL/freeglut.h>

GLint TopLeftX, TopLeftY, BottomRightX, BottomRightY;
//마우스로 드래그 한 사각형의 좌측 상단과 우측 하단의 좌표를 저장하기 위한 변수

void MyDisplay() {		//사각형 그리기
    glViewport(0, 0, 300, 300);			//뷰포트 설정
    glClear(GL_COLOR_BUFFER_BIT);		//컬러버퍼에 초기화 색을 가함
    glColor3f(0.5, 0.5, 0.5);			//그릴 도형의 색상 지정 : 회색
    glBegin(GL_POLYGON);			//도형을 그리기 위한 시작 지점 설정, 사각형 그리기
    	//사각형 꼭짓점 좌표 설정 (300으로 나누어서 정규화함)
        glVertex3f(TopLeftX / 300.0, (300 - TopLeftY) / 300.0, 0.0);
        glVertex3f(TopLeftX / 300.0, (300 - BottomRightY) / 300.0, 0.0);
        glVertex3f(BottomRightX / 300.0, (300 - BottomRightY) / 300.0, 0.0);
        glVertex3f(BottomRightX / 300.0, (300 - TopLeftY) / 300.0, 0.0);
    glEnd();			//도형 그리기 종료
    glFlush();			//명령어 버퍼에 쌓인 명령어 실행
}
void MyMouseClick(GLint Button, GLint State, GLint X, GLint Y) {
//마우스 버튼이 눌렸을 때 좌표를 저장
    if (Button == GLUT_LEFT_BUTTON && State == GLUT_DOWN) { //왼쪽 버튼 & 버튼이 눌렸을 때
        TopLeftX = X;
        TopLeftY = Y;
    }
}
void MyMouseMove(GLint X, GLint Y) {	//마우스가 움직이는 동안 좌표 업데이트
    BottomRightX = X;
    BottomRightY = Y;
    glutPostRedisplay();		
    //다른 콜백함수에서 어떤 값을 바꾸고 바뀐 값을 기준으로 새로이 화면 디스플레이를 원할 때, 화면을 다시 그리도록 하기
}
int main(int argc, char** argv) {
    glutInit(&argc, argv);			//GLUT 라이브러리를 초기화함
    glutInitDisplayMode(GLUT_RGB);		//디스플레이 모드를 RGB 컬러 모드로 설정함
    glutInitWindowSize(300, 300);		//윈도우 크기 설정
    glutInitWindowPosition(0, 0);		//윈도우 위치 설정
    glutCreateWindow("OpenGL Example Drawing"); //윈도우 생성

    glClearColor(1.0, 1.0, 1.0, 1.0);   	//초기화 색은 백색
    glMatrixMode(GL_PROJECTION);		//행렬 모드를 GL_PROJECTION으로 설정
    glLoadIdentity();				//현재의 행렬 상태 초기화함.
    glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);	//뷰포트의 좌표계 설정

    glutDisplayFunc(MyDisplay);			//디스플레이 콜백 함수 등록
    glutMouseFunc(MyMouseClick);		//마우스 클릭 이벤트에 따른 콜백 등록
    glutMotionFunc(MyMouseMove);		//마우스를 누른 상태에서 움직이는 이벤트에 따른 콜백 등록
    glutMainLoop();				//이벤트 루프 실행
    return 0;
}

더보기
  • void glutMotionFunc(void(*func) (int x, int y)) : 마우스 포인터가 윈도우 내에서 움직일 때마다 호출되는 콜백 함수를 등록함. 이 콜백 함수는 현재 마우스 포인터 위치의 x, y 좌표를 인수로 받음. 마우스 버튼이 눌려져 있을 때에도 호출됨
  • void glutPassiveMotionFunc(void(*func) (int x, int y)) : 마우스 버튼이 눌려지지 않은 상태에서 마우스 포인터가 윈도우 내에서 움직일 때마다 호출되는 콜백 함수를 등록함. 이 콜백 함수는 현재 마우스 포인터 위치의 x, y 좌표를 인수로 받음.
  • void glutEntryFunc(void(*func) (int state)) : 윈도우로의 진입/이탈 이벤트가 발생할 때마다 호출되는 콜백 함수를 등록함. 이 콜백 함수는 현재 윈도우 상태(진입한 경우 1, 이탈한 경우 0)를 나타내는 정수값을 인수로 받음.

glutPostRedisplay() 함수는 변수 값이 변경 되었으므로 다음 이벤트 루프가 돌 때 반드시 디스플레이 함수를 다시 실행하라는 것.

댓글