ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OpenGL 강좌 - 삼각형이 회전하는 애니메이션 구현
    OpenGL/OpenGL 2.x 강좌 2016. 12. 20. 10:29

    본 포스팅을 보기 전에 아래 포스팅을 참고하세요..

    [그래픽스&컴퓨터비전/OpenGL & Augmented Reality] - OpenGL 강좌 - 정사각형 그리기


    OpenGL 프로그래밍을 위한 준비는 다음 포스팅을 참고하세요.

    [그래픽스&컴퓨터비전/OpenGL & Augmented Reality] - Ubuntu 16.04에서 OpenGL( freeGLUT ) 프로그래밍

    [그래픽스&컴퓨터비전/OpenGL & Augmented Reality] - OpenGL( freeGLUT ) 을 Visual Studio 2015에 연동하기



    이번엔 삼각형의 중앙이 원점(0,0)에 오도록해서 그리는 예제입니다. 주의 할 점은 삼각형을 구성하는 세 개의 vertex를 지정해줄 때 반드시 반시계 방향으로 차례대로 지정해줘야 합니다.

    1
    2
    3
    4
    5
    6
    7
    8
        glBegin(GL_TRIANGLES); //3점이 하나의 삼각형을 구성한다. 반시계 방향으로 3점의 vertex를 지정해줘야 한다.
        glColor3f(1.0f, 0.0f, 0.0f); //빨간색 지정
        glVertex3f(-0.5f, -0.5f, 0.0f);    // 왼쪽 아래 vertex
        glColor3f(0.0f, 1.0f, 0.0f); //녹색 지정
        glVertex3f(0.5f, -0.5f, 0.0f);    // 오른쪽 아래 vertex
        glColor3f(0.0f, 0.0f, 1.0f); //파란색 지정
        glVertex3f(0.0f, 0.5f, 0.0f);    // 위쪽 vertex
        glEnd();
    cs




    애니메이션을 구현하기 위해서는 타이머 콜백 함수를 등록해야 합니다.  타이머 콜백 함수는 지정해준 시간이 지나면 호출됩니다. 처음에는 바로 호출되도록 타이머 이벤트 대기 시간을 0으로 지정해줍니다.

    1
    2
        //타이머 콜백 함수 등록, 처음에는 바로 호출됨.
        glutTimerFunc(0, timer, 0);
    cs

    타이머 콜백 함수에서 glutPostRedisplay 함수를 호출합니다. glutPostRedisplay 함수는 윈도우를 다시 그리도록 요청합니다.  요청하자마자 바로 디스플레이 콜백 함수가 호출되지는 않고 메인 루프에서 호출 시점을 결정하게 됩니다.  다음 타이머 이벤트 대기시간을 30밀리세컨트로 지정해줍니다.

    1
    2
    3
    4
    5
    void timer(int value) {
        glutPostRedisplay();      //윈도우를 다시 그리도록 요청
        glutTimerFunc(30, timer, 0); //다음 타이머 이벤트는 30밀리세컨트 후  호출됨.
    }
     
    cs


    또한 화면 그리는 성능을 높이기 위해 더블 버퍼를 설정해주어야 합니다.

    1
        glutInitDisplayMode(GLUT_DOUBLE); //더블 버퍼를 사용하도록 설정
    cs


    display 콜백 함수 마지막에  glutSwapBuffers 함수를 호출함으로써 프론트 버퍼와 백 버퍼간의 교환이 이루어집니다.

    1
    2
    3
    4
    5
    6
        //더블 버퍼링을 하고 있다면, 프론트 버퍼와 백 버퍼 2개가 사용된다.현재 화면에 보여지는 것은 프론트 버퍼에 있는 내용이다.
        //백 버퍼는 다음 장면을 위해 렌더링을 하고 있는 곳이다.백 버퍼의 렌더링이 완료되면 두 개의 버퍼를 교환(swap)한다.
        //화면에 업데이트된 프론트 버퍼에 있는 내용이 출력된다.
     
        //싱글 버퍼라면 버퍼에 있는 것을 화면에 출력한다.
        glutSwapBuffers();
    cs




    굵은 글씨가 이전 포스팅에서 수정된 부분들입니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    //상대경로로 헤더파일을 지정합니다.
    #include ".\include\GL\freeglut.h"
    #include <iostream>
     
    //사용할 라이브러리를 지정해줍니다.
    #pragma comment(lib, "freeglut.lib")
    #pragma comment(lib, "glew32.lib")
     
    using namespace std;
     
     
    GLfloat current_angle = 0.0f; //삼각형의 현재 회전 각도
     
    void keyboard(unsigned char key, int x, int y)
    {
        cout << "다음 키가 눌러졌습니다. \"" << key << "\" ASCII: " << (int)key << endl;
     
        //ESC 키가 눌러졌다면 프로그램 종료
        if (key == 27)
        {
            exit(0);
        }
    }
     
     
    void drawBitmapText(char *str, float x, float y, float z)
    {
        glRasterPos3f(x, y, z); //문자열이 그려질 위치 지정
     
        while(*str)
        {
            //GLUT_BITMAP_TIMES_ROMAN_24 폰트를 사용하여 문자열을 그린다.
            glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *str);
     
            str++;
        }
    }
     
     
    void display() 
    {
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //glClear에서 컬러 버퍼 지운 후 윈도우를 채울 색을 지정, 검은색
        glClear(GL_COLOR_BUFFER_BIT); //컬러 버퍼를 지운다.
     
        glMatrixMode(GL_MODELVIEW); //이후 계산은 modelview matrix에 영향을 주게됨
        glLoadIdentity(); //modleview matrix를 초기화
     
        //z축을 중심으로 설정된 current_angle로 회전한다.
        glRotatef(current_angle, 0.0f, 0.0f, 1.0f);
        
        //중앙이 원점에 오도록 삼각형을 그린다. 
        glBegin(GL_TRIANGLES); //3점이 하나의 삼각형을 구성한다. 반시계 방향으로 3점의 vertex를 지정해줘야 한다.
        glColor3f(1.0f, 0.0f, 0.0f); //빨간색 지정
        glVertex3f(-0.5f, -0.5f, 0.0f);    // 왼쪽 아래 vertex
        glColor3f(0.0f, 1.0f, 0.0f); //녹색 지정
        glVertex3f(0.5f, -0.5f, 0.0f);    // 오른쪽 아래 vertex
        glColor3f(0.0f, 0.0f, 1.0f); //파란색 지정
        glVertex3f(0.0f, 0.5f, 0.0f);    // 위쪽 vertex
        glEnd();
     
        glColor3f(1.0f, 1.0f, 1.0f);//흰색 지정
        drawBitmapText("-0.5, -0.5"-0.5f, -0.5f, 0.0f);// 지정한 좌표에 문자열 출력
        drawBitmapText("0.5, -0.5"0.5f, -0.5f, 0.0f);
        drawBitmapText("0.0, 0.5"0.0f, 0.5f, 0.0f);
        
        //display 함수 호출될때마다 회전각도 증가시킴
        current_angle += 0.5;
        cout << current_angle << endl;
     
     
        //더블 버퍼링을 하고 있다면, 프론트 버퍼와 백 버퍼 2개가 사용된다.현재 화면에 보여지는 것은 프론트 버퍼에 있는 내용이다.
        //백 버퍼는 다음 장면을 위해 렌더링을 하고 있는 곳이다.백 버퍼의 렌더링이 완료되면 두 개의 버퍼를 교환(swap)한다.
        //화면에 업데이트된 프론트 버퍼에 있는 내용이 출력된다.
     
        //싱글 버퍼라면 버퍼에 있는 것을 화면에 출력한다.
        glutSwapBuffers();
    }
     
     
    void reshape(GLsizei width, GLsizei height) 
    {  
        if (height == 0) height = 1;                // 0으로 나누는 것 방지
        GLfloat aspect = (GLfloat)width / (GLfloat)height;
     
        //변경된 윈도우크기로 viewport를 설정한다.
        glViewport(00, width, height);
     
        glMatrixMode(GL_PROJECTION);  //뒤에 오는 계산들은 Projection matrix에 영향을 주도록 설정
        glLoadIdentity();             //projection matrix 초기화
        if ( width >= height) {
            // aspect >= 1 이면, height를 [-1,1]로 설정하고 width는 [-1*aspect, 1*aspect]로 설정한다.
            // left, right, top, bottom
            gluOrtho2D(-1.0 * aspect, 1.0 * aspect, -1.01.0);
        }
        else {
            // aspect < 1이면, width를 [-1,1]로 설정하고 height를  [-1/aspect, 1/aspect]로 설정한다.
            gluOrtho2D(-1.01.0-1.0 / aspect, 1.0 / aspect);
        }
     
        //뒤에 오는 계산들은 Modelview Matrix에 영향을 주도록 설정한다. 
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity(); //Modelview matrix 초기화
    }
     
     
    void timer(int value) {
        glutPostRedisplay();      //윈도우를 다시 그리도록 요청
        glutTimerFunc(30, timer, 0); //다음 타이머 이벤트는 30밀리세컨트 후  호출됨.
    }
     
     
    int main(int argc, char** argv) 
    {
        glutInit(&argc, argv);  //GLUT 초기화
     
        glutInitDisplayMode(GLUT_DOUBLE); //더블 버퍼를 사용하도록 설정
        glutInitWindowSize(500500);   //윈도우의 width와 height
        glutInitWindowPosition(100100); //윈도우의 위치 (x,y)
        glutCreateWindow("OpenGL Example"); //윈도우 생성
     
        //디스플레이 콜백 함수 등록, display함수는 윈도우 처음 생성할 때와 화면 다시 그릴 필요 있을때 호출된다. 
        glutDisplayFunc(display); 
        //키보드 콜백 함수 등록, 키보드가 눌러지면 호출된다. 
        glutKeyboardFunc(keyboard);
        //reshape 콜백 함수 등록, reshape함수는 윈도우 처음 생성할 때와 윈도우 크기 변경시 호출된다.
        glutReshapeFunc(reshape);
        //타이머 콜백 함수 등록, 처음에는 바로 호출됨.
        glutTimerFunc(0, timer, 0);
     
        //GLUT event processing loop에 진입한다.
        //이 함수는 리턴되지 않기 때문에 다음줄에 있는 코드가 실행되지 않는다. 
        glutMainLoop();          
     
        return 0;
    }
    cs


    포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
    댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

    여러분의 응원으로 좋은 컨텐츠가 만들어집니다. 지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다. 감사합니다 : )

    유튜브 구독하기


    댓글 0

Designed by Tistory.