Implement of Input and Interaction Hanyang University
Objective Viewport and Ortho Callback Programming Reshape Callback Keyboard Callback SpecialKey Callback Mouse Callback Menu Callback
Viewport and ortho glViewport 윈도우 상에서 그림이 그려질 영역을 설정한다. glViewport(GLint x, GLint y, GLsizei width, GLsizei height); x : 영역의 좌 하단 x 좌표 y : 영역의 우 하단 y 좌표 width : 영역의 너비 height : 영역의 높이 EX ) … glutInitWindowSize(400, 300); glViewport(100, 80, 160, 100); Viewport 400 (window width) 300 (window height) 원점 y = 80 x = 100 width = 160 height = 100
3차원의 OpenGL 공간을 2차원의 윈도우에 어떻게 투영할 것인가? 가시부피 설정 glOrtho( 직교투영(PROJECTION) 함수 3차원의 OpenGL 공간을 2차원의 윈도우에 어떻게 투영할 것인가? 가시부피 설정 glOrtho( GLdouble left, GLdouble right, // x축 범위 GLdouble bottom, GLdouble top, // y축 범위 GLdouble near, GLdouble far // z축 범위 ); Default 설정 glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); (right, top, far) (left, bottom, near) view
Example source #include <gl/glut.h> void MyDisplay() { glClear(GL_COLOR_BUFFER_BIT); glViewport(100, 100, 200, 200); glBegin(GL_QUADS); // 그리기 색 (Red, Green, Blue) (적색) glColor3f(1.0, 0.0, 0.0); glVertex3f(0, 0, 0.0); glVertex3f(640, 0, 0.0); glVertex3f(640, 480, 0.0); glVertex3f(0, 480, 0.0); // 그리기 색 (Red, Green, Blue) (회색) glColor3f(0.5, 0.5, 0.5); glVertex3f(160, 120, 0.0); glVertex3f(480, 120, 0.0); glVertex3f(480, 360, 0.0); glVertex3f(160, 360, 0.0); glEnd(); glFlush(); } int main(int argc, char** argv) { glutInitDisplayMode(GLUT_RGB); glutInitWindowSize(640, 480); // 윈도우창 크기 설정 (width, height) glutInitWindowPosition(0, 0); // 윈도창의 시작 위치 (x, y) glutCreateWindow("OpenGL Drawing Example"); // 윈도우 바탕 색 (Red, Green, Blue, Alpha) (흰색) glClearColor(1.0, 1.0, 1.0, 1.0); // Ortho 설정을 위해서는 다음 두 함수가 선행 되어져야 함. glMatrixMode(GL_PROJECTION); // 투영좌표계설정 glLoadIdentity(); //좌표계초기화 glOrtho(0.0, 640.0, 0.0, 480.0, -1.0, 1.0); glutDisplayFunc(MyDisplay); glutMainLoop(); return 0; }
Reshape Callback 윈도우의 크기나 모양이 바뀔 때 GLUT가 호출하는 콜백 함수를 등록 void glutReshapeFunc(void(*func)(int width, int height)); width : 윈도우의 새로운 너비 height : 윈도우의 새로운 높이 //reshape 콜백 함수 선언 void MyReshapde(int NewWidth, int NewHeight) { … } int main(int argc, char** argv) glutReshapeFunc(MyReshapde); //reshape 콜백 함수 등록
Example Source #include <gl/glut.h> void MyDisplay() { glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.5, 0.5, 0.5); 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 MyReshapde(int NewWidth, int NewHeight) glViewport(0, 0, NewWidth, NewHeight); //뷰포트 크기를 변경된 윈도우 크기와 일치 시킨다. GLfloat WidthFactor = (GLfloat)NewWidth / (GLfloat)300; GLfloat HeightFactor = (GLfloat)NewHeight / (GLfloat)300; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1.0 * WidthFactor , 1.0 * WidthFactor, -1.0 * HeightFactor, 1.0 * HeightFactor, -1.0, 1.0); int main(int argc, char** argv) glutInitWindowSize(300, 300); glutCreateWindow("OpenGL Drawing Example"); glClearColor(1.0, 1.0, 1.0, 1.0); glutDisplayFunc(MyDisplay); glutReshapeFunc(MyReshapde); glutMainLoop(); return 0;
Keyboard Callback 키보드 입력이 일어날 때마다 GLUT가 호출하는 콜백 함수를 등록 void glutKeyboardFunc(void(*func)(unsigned char key, int x, int y)); key : 키보드의 눌려진 키 x : 마우스의 x 좌표 y : 마우스의 y 좌표 //키보드 콜백 함수 선언 void MyKeyboard(unsigned char KeyPressed, int X, int Y) { … } int main(int argc, char** argv) glutKeyboardFunc(MyKeyboard); //키보드 콜백 함수 등록
Example Source #include <gl/glut.h> void MyDisplay() { glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.5, 0.5, 0.5); 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) switch(KeyPressed) case 'Q' : exit(0); break; case 'q' : exit(0); break; case 27 : exit(0); break; // ESC 키 int main(int argc, char** argv) glutInitWindowSize(300, 300); glutCreateWindow("OpenGL Drawing Example"); glClearColor(1.0, 1.0, 1.0, 1.0); glutDisplayFunc(MyDisplay); glutKeyboardFunc(MyKeyboard); glutMainLoop(); return 0;
SpecialKey Callback 특수키 입력이 일어날 때마다 GLUT가 호출하는 콜백 함수를 등록 기능키(F1~F12), 방향키, insert, home, end, page up, page down void glutSpecialFunc(void(*func)(int key, int x, int y)); key : 키보드의 눌려진 특수키 x : 마우스의 x 좌표 y : 마우스의 y 좌표 사용법은 keyboard callback과 비슷함.
SpecialKey Callback 기능키 값 방향키 값 그 외 GLUT_KEY_F1 ~ GLUT_KEY_F12 GLUT_KEY_LEFT GLUT_KEY_UP GLUT_KEY_RIGHT GLUT_KEY_DOWN 그 외 GLUT_KEY_PAGE_UP GLUT_KEY_PAGE_DOWN GLUT_KEY_HOME GLUT_KEY_END GLUT_KEY_INSERT //특수키 콜백 함수 선언 void MySpecialKey(int KeyPressed, int X, int Y) { ... switch (KeyPressed) case GLUT_KEY_LEFT: } int main(int argc, char** argv) … glutSpecialFunc(MySpecialKey); //특수키 콜백 함수 등록
Mouse Callback(click) 마우스 이벤트가 발생할 때마다 GLUT가 호출하는 마우스 클릭 콜백 함수를 등록 void glutMouseFunc(void(*func)(int button, int state, int x, int y)); button : 버튼의 종류를 뜻하는 상수값 버튼의 종류 : GLUT_LEFT_BUTTON GLUT_RIGHT_BUTTON GLUT_MIDDLE_BUTTON State : 해당 버튼이 눌러진 상태인지 아닌지를 알려주는 상수값 버튼의 상태 : GLUT_DOWN, GLUT_UP x : 마우스의 x좌표 y : 마우스의 y좌표
Mouse Callback(click) 마우스 클릭 콜백 함수 등록 //마우스 클릭 콜백 함수 선언 void MyMouseClick(GLint Button, GLint State, GLint X, GLint Y) { if(Button == GLUT_LEFT_BUTTON && State == GLUT_DOWN) … } int main(int argc, char** argv) glutMouseFunc(MyMouseClick); //마우스 클릭 콜백 함수 등록
Mouse Callback(motion) 버튼을 누른 상태에서 마우스를 움직일 때 호출되는 마우스 움직임 콜백 함수를 등록 void glutMotionFunc(void(*func)(int x, int y)); x : 마우스의 x 좌표 y : 마우스의 y 좌표 //마우스 움직임 콜백 함수 선언 void MyMouseMove(GLint X, GLint Y) { … } int main(int argc, char** argv) glutMotionFunc(MyMouseMove); //마우스 움직임 콜백 함수 등록
Example Source 마우스 왼클릭 후 드래그한 영역에 사각형을 그리는 예제 #include <gl/glut.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) glutInitWindowSize(300, 300); 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;
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); => => <= 좌표변환 필요 : Window 좌표계를 OpenGL좌표계로 매핑시킨다. 윈도우 x좌표에서 OpenGL x좌표로 변환 = 윈도우 X좌표 / 300 윈도우 y좌표에서 OpenGL y좌표로 변환 = (300 - 윈도우 Y좌표) / 300 v1x = TopLeftX / 300; v1y = (300 - TopLeftY) / 300; v2x = TopLeftX / 300; v2y = (300 - BottomRightY) / 300; v3x = BottomRightX / 300; v3y = (300 - BottomRightY) / 300; v4x = BottomRightX / 300; v4y = (300 - TopLeftY) / 300;
Menu Callback 메뉴 선택시 호출되는 메뉴 콜백 함수를 등록하는 함수 - int glutCreateMenu(void(*func)(int value)); 리턴값 : 해당 메뉴의 고유 아이디값 value : 엔트리 아이디 값 void MyMainMenu(int entryID) { if(entryID == 1) … else if(entryID == 2) } int main(int argc, char** argv) GLint MyMainMenuID = glutCreateMenu(MyMainMenu);
Menu Callback Id에 해당하는 메뉴를 이용한다. - int glutSetMenu(int id) id : glutCreateMenu()에 리턴되는 값 void MyMainMenu1(int entryID) { … } void MyMainMenu2(int entryID) int main(int argc, char** argv) GLint MyMainMenuID1 = glutCreateMenu(MyMainMenu1); GLint MyMainMenuID2 = glutCreateMenu(MyMainMenu2); glutSetMenu(MyMainMenuID2);
Menu Callback 메뉴 항목을 추가한다. - int glutAddMenuEntry(char *name, int value); name : 항목의 이름 value : 해당 항목이 선택될 때 메뉴 콜백함수에게 전달되는 정수값 void MyMainMenu(int entryID) { if(entryID == 1) … //Draw Sphere 선택 else if(entryID == 2) … //Draw Torus 선택 } int main(int argc, char** argv) … GLint MyMainMenuID = glutCreateMenu(MyMainMenu); glutAddMenuEntry(“Draw Sphere”, 1); glutAddMenuEntry(“Draw Torus”, 2);
Menu Callback 지정한 마우스 버튼에 메뉴가 적용된다. - int glutAttachMenu(int button); GLUT_LEFT_BUTTON : 마우스 왼쪽 버튼 GLUT_RIGHT_BUTTON : 마우스 오른쪽 버튼 GLUT_MIDDLE_BUTTON : 마우스 가운데 버튼 int main(int argc, char** argv) { … GLint MyMainMenuID = glutCreateMenu(MyMainMenu); glutAttachMenu(GLUT_RIGHT_BUTTON); }
Menu Callback 서브 메뉴가 있는 메뉴를 추가한다 - int glutAddSubMenu(char *name, int menu); name : 서브 메뉴 항목의 이름 menu : glutCreateMenu()에 의해 해당 서브메뉴를 만들 때 리턴된 메뉴 아이디 값 void MySubMenu(int entryID) { } int main(int argc, char** argv) … GLint MySubMenuID= glutCreateMenu(MySubMenu); glutAddSubMenu("Change Size", MySubMenuID);
Example Source #include <gl/glut.h> GLboolean IsSphere = true; GLboolean IsSmall = true; void MyDisplay() { glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.5, 0.5, 0.5); if((IsSphere) && (IsSmall)) glutWireSphere(0.2, 15, 15); // 작은 Wire(선으로 이루어진) Sphere(구(球)) else if((IsSphere) && (!IsSmall)) glutWireSphere(0.4, 15, 15); // 큰 Sphere else if((!IsSphere) && (IsSmall)) glutWireTorus(0.1, 0.3, 40, 20); // 작은 Wire Torus(도넛형 고리) else glutWireTorus(0.2, 0.5, 40, 20); // 큰 Torus glFlush(); } void MyMainMenu(int entryID) if(entryID == 1) IsSphere = true; // Draw Sphere 선택 else if(entryID == 2) IsSphere = false; // Draw Torus 선택 else if(entryID == 3) exit(0); // Exit 선택 glutPostRedisplay();
void MySubMenu(int entryID) { if(entryID == 1) IsSmall = true; //Small One선택 else if(entryID == 2) IsSmall = false; //Big One선택 glutPostRedisplay(); } int main(int argc, char** argv) glutInitWindowSize(300, 300); glutCreateWindow("OpenGL Drawing Example"); glClearColor(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); glutAddSubMenu("Change Size", MySubMenuID); glutAddMenuEntry("Exit", 3); glutAttachMenu(GLUT_RIGHT_BUTTON); glutDisplayFunc(MyDisplay); glutMainLoop(); return 0;