Scientia Conditorium

[OpenGL 004] Keyboard Callback 등록 본문

프로그래밍/컴퓨터 그래픽스

[OpenGL 004] Keyboard Callback 등록

크썸 2024. 12. 18. 00:37

이전글 : [OpenGL003] Refresh Callback 함수 등록

 

[OpenGL003] Refresh Callback 함수 등록

이전글 : [OpenGL002] glew 설치 및 에러 수정 [OpenGL002] glew 설치 및 에러 수정이전 글 : [OpenGL001] Visual Studio 2022 with OpenGL,GLFW (tistory.com) [OpenGL001] Visual Studio 2022 with OpenGL,GLFW※ 본 글은 Window10 + Visual Stud

molonlabe.tistory.com


Keyboard Callback 함수

이전 포스팅에서는 Refresh 콜백 함수를 등록해보았습니다. refresh 콜백 함수를 통해 윈도우 창이 조절될 때마다 등록한 함수가 호출되는 것을 확인했습니다. 이번에는 비슷하게 사용자의 키보드 입력을 받으면 특정 동작을 수행하는 콜백 함수를 등록해보겠습니다. glfw3.h 헤더 파일에서 키보드 콜백 함수 GLFWKeyfun 을 검색하면 아래와 같은 주석을 확인할 수 있습니다. 

 

키보드 콜백 함수 원형은 경우 아래와 같습니다.

typedef void (* GLFWkeyfun)(GLFWwindow* window, int key, int scancode, int action, int mods);

 

등록하는 방법은 비슷하니 이 포스팅에서는 파라미터 설명에 중심을 두겠습니다.

  1. GLFWwindow* win
    • 타켓 윈도우입니다. 이벤트를 받을 윈도우 창을 입력 받습니다.
  2. int key
    • 누르거나(pressed) 떼었을 때(released)의 키보드 키 값을 의미합니다.
  3. int scancode
    • 플랫폼 또는 키보드 하드웨어에 정의된 값으로 키가 눌렸을 때 키의 물리적 위치를 나타냅니다. 운영 체제가 키보드 드라이버와 상호작용 할 때 사용되며 게임 컨트롤이나 특정 동작을 구현할 때 유용합니다. 대부분의 경우 사용하지 않습니다.
  4. int action
    1. 키보드의 동작을 나타냅니다. 가장 대표적으로 키보드를 눌렀을 때(GLFW_PRESS), 키보드를 뗐을 때(GLFW_RELEASE), 키보드에서 자동 반복하고 있는 상황이냐(GLFW_REPEAT)가 있습니다. GLFW 버전이 올라가면 다른 동작들도 추가될 것이라고 주석에 설명되어 있지만 3개의 동작을 알아도 충분합니다.
  5. int mods
    1. 키보드의 일반적인 키 말고, shift, ctrl, alt, windows 등등 수정 키를 의미합니다. 비트 필드로 설정되는데 사용 방법은 바로 아래에서 설명하겠습니다.

 

 

GLFW keyboard callback 입력 방법 예시

가령 키보드에서 CTRL + SHIFT + 'C' 키를 입력받는 경우를 등록하고 싶다고 가정해봅시다. 그러면 다음과 같이 코드를 작성하면 되겠습니다.

// C + SHIFT + CTRL 키를 입력 받았을 때 특정 함수 동작 예시 코드
// key = 'C'
// mods = GLFW_MOD_SHIFT | GLFW_MOD_CONTROL
// action = GLFW_PRESS

void keyFunc(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if ((key == GLFW_KEY_C) &&
    	(action == GLFW_PRESS) &&
    	(mods == GLFW_MOD_SHIFT | GLFW_MOD_CONTROL))
    {
    	activate_airship();
    }
}

 

위 예제 코드에서는 window 타켓을 생략했습니다. 

 

ESC 키를 누르면 프로그램이 종료되는 코드

우선은 가장 간단하게 ESC 키를 누르면 프로그램이 종료되는 코드를 작성해보려 합니다. 나중에 가서는 슈팅 게임처럼 W, A, S, D 입력 받아 상하좌우로 움직이거나 특별한 동작을 하는 코드도 추가하겠습니다. 키보드 콜백 역시 refresh 콜백 함수와 비슷한 역할을 하므로 Renderer 클래스에 static 함수로 만들겠습니다.

void Renderer::keyFunc(GLFWwindow* window, int key, int scancode, int action, int mods)
{
	switch (key)
	{
	case GLFW_KEY_ESCAPE:
	{
		if (action == GLFW_PRESS)
		{
			glfwSetWindowShouldClose(window, GL_TRUE);
		}
		break;
	}
	default:
	{
		break;
	}
	}
}

 

기능을 추가할 때마다 두 번째 파라미터 key 값의 입력이 많아질테니 미리 switch 문으로 만들었습니다. 그런 다음 가장 대표적으로 ESC키를 의미하는 'GLFW_KEY_ESCAPE' 일 때와 해당 키보드 입력의 action이 GLFW_PRESS 즉, ESC키를 눌렀을 때 glfw 윈도우 창이 종료하는 함수를 호출하도록 하였습니다.

 

glfwSetWindowShouldClose 함수의 정의는 다음과 같습니다.

 

즉, 파라미터로 입력한 윈도우 창의 닫기 플래그를 설정하는 함수입니다. 우리가 키보드 ESC를 눌러서 이 함수를 호출했을 경우 바로 종료되는 것은 아닙니다. 말 그대로 닫기 플래그를 설정하는 것이죠. 그러면 어디서 종료가 되느냐?. Renderer의 run 함수로 돌아가보겠습니다.

void Renderer::run()
{
	while (!glfwWindowShouldClose(mWindow))
	{
		glClear(GL_COLOR_BUFFER_BIT);
		glBegin(GL_TRIANGLES);
		glColor3f(1.0f, 0.0f, 0.0f);
		glVertex2f(-0.5f, 0.0f);
		glVertex2f(0.0f, 0.5f);
		glVertex2f(0.5f, 0.0f);
		glEnd();

		glfwSwapBuffers(mWindow);
		glfwPollEvents();
	}
}

while문을 반복할 때 사용하는 조건문에서 glfwWindowShoudClose 함수를 사용했습니다. 복습을 하자면 이 함수는 파라미터로 받은 윈도우 창의 닫기 플래그에 설정된 값을 반환합니다. 우리는 ESC키로 닫기 플래그의 값을 TRUE로 설정했기 때문에 glfwWindowShouldClose 함수는 true를 반환하게 될테고 앞에 ! 에 의해서 false로 바뀌게 됩니다. 그러면 while문을 빠져나오게 되고 프로그램이 정상 종료하게 됩니다. 물론 윈도우 창이나 프로그램을 강제 종료시켜 버리는 방법도 있지만 메모리 관리나 다른 동작도 할 수 있음을 염두에 두었으면 합니다. 게다가 프로그래밍에 정답이 없기 때문에 이 포스팅을 읽고 계시는 여러분들이 하고 싶은대로 작성하시면 되겠습니다.

 

다음 글에서는 키보드 값을 여러개 입력 받아 화면의 색상을 바꾸는 프로그램을 만들어보겠습니다.