OpenGL 콜백함수

2020. 9. 21. 20:06Computer Graphics/OpenGl

마우스 콜백

 

마우스가 움직이거나 눌러질 때 발생하는 함수를 의미한다. 

아래와 같은 네가지 함수가 존재한다. 

glutMouseFunc(void (*func)(int button, int state, int x, int y));
glutMotionFunc(void (*func)(int x, int y));
glutPassiveMotionFunc(void (*func)(int x, int y));
glutEntryFunc(void(*func)(int state));

 

glutMouseFunc(void (*func)(int button, int state, int x, int y));

마우스 버튼을 눌렀을때 와 땔때 모두  사용할 수 있다. 
button에는 GLUT_LEFT_BUTTON, GLUT_RIGHT_BUTTON, GLUT_MIDDLE_BUTTON 을 통해 가운데 버튼, 왼쪽 버튼, 오른쪽 버튼을 구분해서 함수를 실행시킬 수 있다. 

 

glutPassiveMotionFunc(void (*func)(int x, int y));

마우스를 안누르고 있을 때 움직이면 해당 좌표값을 콜백함수에 넘겨준다. 

 

glutEntryFunc(void (*func)(int state));

윈도우 창으로 들어갈 때와 나올때를 선택해 이벤트를 발생시킬 수 있다.


예제 코드

//
//  main.cpp
//  Week3
//
//  Created by 이상훈 on 2020/09/21.
//  Copyright © 2020 이상훈. All rights reserved.
//

#include <iostream>
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#include <stdlib.h>

#define _WINDOW_HEIGHT 600
#define _WINDOW_WIDTH 600

GLfloat r = 1.0, g= 1.0, b = 1.0;
GLint cur_x = -1, cur_y = -1;
int mode, mode_visual = 1, canClick = 0;

void reshape(int width, int height){
    glViewport(0, 0, width, height);
    GLfloat f_w = (GLfloat)width/(GLfloat)_WINDOW_WIDTH;
    GLfloat f_h = (GLfloat)height/(GLfloat)_WINDOW_HEIGHT;
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1.0 * f_w, 1.0 * f_w, -1.0 * f_h, 1.0 * f_h, -1, 1);
}

void display(){
    glClear(GL_COLOR_BUFFER_BIT);
    if(mode_visual == 1){
        if (mode == 0)
              glutWireSphere(0.3, 15, 15);
          else
              glutWireTeapot(0.7);
    }else{
        
    }
    glFlush();
}

void mouseBtn(int btn, int states, int x, int y){
    if(btn == GLUT_LEFT_BUTTON && states == GLUT_UP ){
        mode = (mode + 1) % 2;
        glutPostRedisplay();
    }
}

void mouseDrag(int x, int y){
    GLint dx, dy;
    canClick = 0;
    if (cur_x >= 0 || cur_y >= 0){
        dx = abs(x - cur_x);
        dy = abs(y - cur_y);
        GLint sum = dx + dy;
        g = (g - 0.1) < 0? 0 : g - 0.1;
        b = (b - 0.1) < 0? 0 : b - 0.1;
        
        glColor3f(r, g, b);
        glutPostRedisplay();
    }
    cur_x = x;
    cur_y = y;
}

void winEntry(int state){
    if (state == GLUT_LEFT)
        mode_visual = 0;
    else
        mode_visual = 1;
    glutPostRedisplay();
}

int main(int argc, char * argv[]) {
    glutInit(&argc, argv);// 초기화
    glutInitDisplayMode(GLUT_RGB);
    glutCreateWindow("title");
    glutInitWindowSize(_WINDOW_WIDTH, _WINDOW_HEIGHT);
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMotionFunc(mouseDrag);
    glutMouseFunc(mouseBtn);
    
    glutEntryFunc(winEntry);
    
    glutMainLoop();
    return 0;
}

 

메뉴 콜백

메뉴를 추가하는 방법을 학습해볼 것입니다. 

 

int glutCreateMenu(void(*func )(int value));

메뉴 콜백함수 등록. 메뉴의 아이디 리턴!

 

glutSetMenu(int id); id 번호를 가진 메뉴를 현재 메뉴로 설정

 

glutAddMenuEntry(char* name, int value); 현재 메뉴에 엔트리 추가!

 

int glutAttachMenu(int button); 특정 마우스 버튼에 현 메뉴 할당!

 

glutAddSubMenu(char *name, int menu); 현재 메뉴에 서브메뉴 추가

 

예제 코드

 

//
//  main.cpp
//  Week3
//
//  Created by 이상훈 on 2020/09/21.
//  Copyright © 2020 이상훈. All rights reserved.
//

#include <iostream>
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#include <stdlib.h>

#define _WINDOW_HEIGHT 600
#define _WINDOW_WIDTH 600

GLfloat r = 1.0, g= 1.0, b = 1.0;
GLint cur_x = -1, cur_y = -1;
int mode;

void reshape(int width, int height){
    glViewport(0, 0, width, height);
    GLfloat f_w = (GLfloat)width/(GLfloat)_WINDOW_WIDTH;
    GLfloat f_h = (GLfloat)height/(GLfloat)_WINDOW_HEIGHT;
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1.0 * f_w, 1.0 * f_w, -1.0 * f_h, 1.0 * f_h, -1, 1);
}

void display(){
    glClear(GL_COLOR_BUFFER_BIT);
    if(mode == 0){
        
    }else if(mode == 1){
        glutWireSphere(0.3, 15, 15);
    }else if(mode == 2){
        glutWireTorus(0.2, 0.5, 15, 15);
    }else
        glutWireTeapot(0.3);
    glFlush();
}


void mouseDrag(int x, int y){
    GLint dx, dy;
    if (cur_x >= 0 || cur_y >= 0){
        dx = abs(x - cur_x);
        dy = abs(y - cur_y);
        GLint sum = dx + dy;
        g = (g - 0.1) < 0? 0 : g - 0.1;
        b = (b - 0.1) < 0? 0 : b - 0.1;
        
        glColor3f(r, g, b);
        glutPostRedisplay();
    }
    cur_x = x;
    cur_y = y;
}

void selectMenu(int value){
    if (value == 2)
        exit(0);
}

void selectSubMenu(int value){
    mode = value;
    glutPostRedisplay();
}

int main(int argc, char * argv[]) {
    glutInit(&argc, argv);// 초기화
    glutInitDisplayMode(GLUT_RGB);
    glutCreateWindow("title");
    glutInitWindowSize(_WINDOW_WIDTH, _WINDOW_HEIGHT);
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMotionFunc(mouseDrag);
    
    
    
    int subMenuId = glutCreateMenu(selectSubMenu);
       glutSetMenu(subMenuId);
       glutAddMenuEntry("Sphere", 1);
       glutAddMenuEntry("Torus", 2);
       glutAddMenuEntry("Teapot", 3);
    
    int mainMenuId = glutCreateMenu(selectMenu);
    glutSetMenu(mainMenuId);
    glutAttachMenu(GLUT_RIGHT_BUTTON);
    glutAddSubMenu("3D Model", subMenuId);
    glutAddMenuEntry("Exit", 2);
       
    
    glutMainLoop();
    return 0;
}

 

 

더블 버퍼링

버퍼를 두개를 두어 데이터의 처리와 전송을 끊킴없이 동시에 할 수 있는 기술이다. 

 

//
//  main.cpp
//  week3_example3
//
//  Created by 이상훈 on 2020/09/21.
//  Copyright © 2020 이상훈. All rights reserved.
//

#include <GLUT/GLUT.h>
#include <OpenGL/OpenGL.h>
#include <iostream>

GLfloat Delta = 0.0;

void MyDisplay(){
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_POLYGON);
    glColor3f(0.0, 0.5, 0.8);
    glVertex3f(-1.0 + Delta, -0.5, 0.0);
    glVertex3f(0.0 + Delta, -0.5, 0.0);
    glVertex3f(0.0 + Delta, 0.5, 0.0);
    glVertex3f(-1.0 + Delta, 0.5, 0.0);
    glEnd();
    glutSwapBuffers();
}

void MyTimer(int value){
    Delta = Delta + 0.01;
    glutPostRedisplay();
    glutTimerFunc(20, MyTimer, value);
}

int main(int argc, char * argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE);
    glutInitWindowSize(600, 600);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("OPENGL WINDOW");
    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);
    
    glutDisplayFunc(MyDisplay);
    glutTimerFunc(20, MyTimer, 1);
    
    glutMainLoop();
    
    return 0;
}

 

'Computer Graphics > OpenGl' 카테고리의 다른 글

Mac OpenGL 설치  (3) 2020.09.01