본문 바로가기

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

[OpenGL] 마우스 콜백 / 2022.10.23

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

 

마우스 이벤트는 마우스 버튼을 누를 때 또는 마우스가 움직일 때 발생한다.

예제를 통해서 알아보자.

1. 마우스 움직임 따라 사각형 그리기

#include <glut.h>
#include <gl/GL.h>
#include <gl/GLU.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);
		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);
	glutInitDisplayMode(GLUT_RGB);
	glutInitWindowSize(300, 300);
	glutInitWindowPosition(0, 0);
	glutCreateWindow("OpenGL Drawing Example");

	glClearColor(1.0, 1.0, 1.0, 1.0);
	glMatrixMode(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;
}

 

- 마우스 콜백 함수와 디스플레이 콜백 함수 사이에 변수를 공유하기 위해 필요한 변수들을 전역 변수로 선언한다.

- TOP 변수는 마우스 왼쪽 버튼이 눌러지면 눌러진 위치의 좌표이고, Button 변수는 현재 마우스 위치를 나타낸다.

전역 변수의 위치

- 마우스를 클릭 했을 떄 MyMouseClick() 함수를, 마우스를 움직일 때 MyMouseMove() 함수를 호출해 변수 값을 변경해준다.

- 변수 값이 변경되면 MyMouseMove() 의 glutPostRedisplay() 함수를 호출하는데, 이 함수는 디스플레이 함수를 다시 실행하라는 함수이다. -> 따라서 디스플레이가 다시 그려진다.

 

결과

2. 윈도우 창의 크기를 바꿔도 사각형을 그릴 수 있는 코드

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

GLint TopLeftX, TopLeftY, BottomRightX, BottomRightY;
GLint Width = 300, Height = 300;

void MyDisplay() {
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(0.5, 0.5, 0.5);
    glBegin(GL_POLYGON);
    glVertex3f(TopLeftX / (GLfloat)Width, (Height - TopLeftY) / (GLfloat)Height, 0.0);
    glVertex3f(TopLeftX / (GLfloat)Width, (Height - BottomRightY) / (GLfloat)Height, 0.0);
    glVertex3f(BottomRightX / (GLfloat)Width, (Height - BottomRightY) / (GLfloat)Height, 0.0);
    glVertex3f(BottomRightX / (GLfloat)Width, (Height - TopLeftY) / (GLfloat)Height, 0.0);
    glEnd();
    glFlush();
}

void MyReshape(int NewWidth, int NewHeight) {
    glViewport(0, 0, NewWidth, NewHeight);
    Width = NewWidth;
    Height = NewHeight;
}

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);
    glutInitDisplayMode(GLUT_RGB);
    glutInitWindowSize(300, 300);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("OpenGL Drawing Example");

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

    glutDisplayFunc(MyDisplay);
    glutReshapeFunc(MyReshape);
    glutMouseFunc(MyMouseClick);
    glutMotionFunc(MyMouseMove);
    glutMainLoop();
    return 0;
}

 

- 윈도우 창의 폭과 높이를 전역변수로 선언한 후 Reshape 함수를 사용하면 됨

 

결과