ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OpenGL 강좌 - 키보드로 3D 큐브(Cube) 움직이기
    OpenGL/OpenGL 2.x 강좌 2016. 12. 29. 15:50


    이전 예제에 이어서 작성합니다.. 정사각형 그리는 방법은 꼭 참고하세요..

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

    [그래픽스&컴퓨터비전/OpenGL & Augmented Reality] - OpenGL 강좌 - 삼각형이 회전하는 애니메이션 구현


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

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

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



    3차원 좌표계에 큐브를 그려놓고 키보드를 이용하여 회전시켜보려고 합니다.  화면 밖이 +Z방향이고, 화면 안쪽이 -Z방향입니다.



    x,y,z 좌표축에 대한 회전은 pitch, yaw, roll이라고 부릅니다.  반시계 방향이 값이 증가하는 방향입니다. 



    코드에서 미리 매칭해놓은 키를 이용하여 설명하겠습니다. Z축에 대한 회전입니다. 키보드에서 +누르면 roll값이 증가하여 반시계 방향으로 회전하고 -값을 누르면 roll값이 감소하여 시계방향으로 회전합니다.


    왼쪽 X축에 대한 회전의 경우 키보드에서 위 방향키를 누르면 pitch값이 증가하여 반시계 방향으로 회전하고 아래 방향키를 누르면  pitch값이 감소하여 시계방향으로 회전합니다.  오른쪽 Y축에 대한 회전의 경우에는 키보드에서 왼쪽 방향키를 누르면 yaw값이 증가하여 반시계 방향으로 회전하고 오른쪽 방향키를 누르면 yaw값이 감소하여 시계방향으로 회전합니다. 


    q/w키로 Z축 이동, a/s키로 Y축 이동, z/x키로 X축 이동이 됩니다. 아래 화면은 q와 w키를 이용하여 Z축을 따라 큐브를 이동시킨 예입니다. 


    전체 소스코드입니다. 

    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
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    //상대경로로 헤더파일을 지정합니다.
    #include ".\include\GL\freeglut.h"
    #include <iostream>
     
    //사용할 라이브러리를 지정해줍니다.
    #pragma comment(lib, "freeglut.lib")
    #pragma comment(lib, "glew32.lib")
     
    using namespace std;
     
     
    //큐브 위치
    float cubeX = 0.0;
    float cubeY = 0.0;
    float cubeZ = -4.0;
     
    //회전
    float pitch = 0.0;
    float yaw = 0.0;
    float roll = 0.0;
     
     
    //float current_angle = 0.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++;
        }
    }
     
     
    //큐브의 한 면, 화면 안쪽 방향인 -Z축방향으로 0.5이동하여 정사각형을 그린다.
    static void cubebase(void)
    {
        glBegin(GL_POLYGON);
        glVertex3d(-0.5-0.5-0.5);
        glVertex3d(-0.50.5-0.5);
        glVertex3d(0.50.5-0.5);
        glVertex3d(0.5-0.5-0.5);
        glEnd();
    }
     
    //cubebase함수에서 그린 사각형을 회전 및 이동시켜
    //큐브를 완성시킨다.
    void draw_cube()
    {
        glMatrixMode(GL_MODELVIEW);
     
     
        glPushMatrix();
     
        glColor3f(0.0f, 1.0f, 0.0f);     // Green, -Z축 방향
        cubebase();
     
        glPushMatrix();
        /*construct side on +x axis*/
        glTranslated(1.00.00.0);
        glRotated(90.00.01.00.0);
        glColor3f(0.0f, 0.0f, 1.0f);     // Blue, +X축 방향
        cubebase();
     
        glPopMatrix();
     
        glPushMatrix();
        glTranslated(-1.00.00.0);
        glRotated(-90.00.01.00.0);
        glColor3f(1.0f, 0.5f, 0.0f);     // Orange, -X축 방향
        cubebase();
        glPopMatrix();
     
        glPushMatrix();
        glTranslated(0.01.00.0);
        glRotated(-90.01.00.00.0);
        glColor3f(1.0f, 0.0f, 0.0f);     // Red, +Y축 방향
        cubebase();
        glPopMatrix();
     
        glPushMatrix();
        glTranslated(0.0-1.00.0);
        glRotated(90.01.00.00.0);
        glColor3f(1.0f, 1.0f, 0.0f);     // Yellow, -Y축 방향
        cubebase();
        glPopMatrix();
     
        glColor3f(1.0f, 0.0f, 1.0f);     // Magenta, +Z축 방향
        glBegin(GL_POLYGON);
        glVertex3d(-0.5-0.50.5);
        glVertex3d(0.5-0.50.5);
        glVertex3d(0.50.50.5);
        glVertex3d(-0.50.50.5);
        glEnd();
     
     
        glPopMatrix();
     
        glFlush();
    }
     
    void draw_line()
    {
        glPushMatrix();
     
        glPushMatrix(); //X축 붉은색
            glColor3f(1.00.00.0);
            glBegin(GL_LINES);
                glVertex3f(5.00.00.0);
                glVertex3f(-5.00.00.0);
            glEnd();
            drawBitmapText("+X"0.80.00.0);
            drawBitmapText("-X"-0.80.00.0);
        glPopMatrix();
     
        glPushMatrix(); //Y축 녹색
            glColor3f(0.01.00.0);
            glBegin(GL_LINES);
                glVertex3f(0.05.00.0);
                glVertex3f(0.0-5.00.0);
            glEnd();
            drawBitmapText("+Y"0.00.80.0);
            drawBitmapText("-Y"0.0-0.80.0);
        glPopMatrix();
     
        glPushMatrix(); //Z축 파란색
            glColor3f(0.00.01.0);
            glBegin(GL_LINES);
                glVertex3f(0.00.05.0);
                glVertex3f(0.00.0-5.0);
            glEnd();
            drawBitmapText("+Z"0.00.00.8);
            drawBitmapText("-Z"0.00.0-0.8);
        glPopMatrix();
     
        glPopMatrix();
     
        glFlush();
    }
     
    void display() 
    {
        //화면을 지운다. (컬러버퍼와 깊이버퍼)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
        //이후 연산은 ModelView Matirx에 영향을 준다. 객체 조작
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
     
        // 이동과 회전을 적용
        glTranslatef(cubeX, cubeY, cubeZ);
        glRotatef(pitch, 1.00.00.0); //x축에 대해 회전
        glRotatef(yaw, 0.01.00.0); //y축에 대해 회전
        glRotatef(roll, 0.00.01.0); //z축에 대해 회전
     
        //큐브를 그림
        draw_cube();
     
        //좌표축을 그림
        draw_line();
     
        glutSwapBuffers();
    }
     
     
    void reshape(GLsizei width, GLsizei height) 
    {  
        glViewport(00, (GLsizei)width, (GLsizei)height); //윈도우 크기로 뷰포인트 설정 
     
        glMatrixMode(GL_PROJECTION); //이후 연산은 Projection Matrix에 영향을 준다. 카메라로 보이는 장면 같은거 설정 
        glLoadIdentity(); 
     
        //Field of view angle(단위 degrees), 윈도우의 aspect ratio, Near와 Far Plane설정
        gluPerspective(45, (GLfloat)width / (GLfloat)height, 1.0100.0); 
     
        glMatrixMode(GL_MODELVIEW); //이후 연산은 ModelView Matirx에 영향을 준다. 객체 조작
    }
     
     
    void timer(int value) {
        //current_angle += 0.5;
        //if (current_angle > 360) current_angle -= 360;
     
        glutPostRedisplay();      //윈도우를 다시 그리도록 요청
        glutTimerFunc(30, timer, 0); //다음 타이머 이벤트는 30밀리세컨트 후  호출됨.
    }
     
     
     
    void init()
    {
        /* Set clear color */
        glClearColor(1.01.01.00.0);
        glClearDepth(1.0);
     
        /* Enable the depth buffer */
        glEnable(GL_DEPTH_TEST);
    }
     
    void special(int key, int x, int y)
    {
        if (key == GLUT_KEY_UP)
        {
            pitch += 1.0;
        }
        else if (key == GLUT_KEY_DOWN)
        {
            pitch -= 1.0;
        }
        else if (key == GLUT_KEY_RIGHT)
        {
            yaw += 1.0;
        }
        else if (key == GLUT_KEY_LEFT)
        {
            yaw -= 1.0;
        }
    }
     
    void keyboard(unsigned char key, int x, int y)
    {
        //cout << "다음 키가 눌러졌습니다. \"" << key << "\" ASCII: " << (int)key << endl;
     
        //ESC 키가 눌러졌다면 프로그램 종료
        if (key == 27)
        {
            exit(0);
        }
        else if (key == 43// +키
        {
            roll += 1.0;
        }
        else if (key == 45//-키
        {
            roll -= 1.0;
        }
        else if (key == 113//q
        {
            cubeZ += 0.1;
        }
        else if (key == 119//w
        {
            cubeZ -= 0.1;
        }
        else if (key == 97//a
        {
            cubeY += 0.1;
        }
        else if (key == 115//s
        {
            cubeY -= 0.1;
        }
        else if (key == 122//z
        {
            cubeX += 0.1;
        }
        else if (key == 120//x
        {
            cubeX -= 0.1;
        }
    }
     
     
     
    int main(int argc, char** argv) 
    {
        glutInit(&argc, argv);  //GLUT 초기화
     
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); //더블 버퍼와 깊이 버퍼를 사용하도록 설정, GLUT_RGB=0x00임
        glutInitWindowSize(500500);   //윈도우의 width와 height
        glutInitWindowPosition(100100); //윈도우의 위치 (x,y)
        glutCreateWindow("OpenGL Example"); //윈도우 생성
     
     
        init();
     
        //디스플레이 콜백 함수 등록, display함수는 윈도우 처음 생성할 때와 화면 다시 그릴 필요 있을때 호출된다. 
        glutDisplayFunc(display); 
     
        //키보드 콜백 함수 등록, 키보드가 눌러지면 호출된다. 
        glutKeyboardFunc(keyboard);
        glutSpecialFunc(special);
        
        //reshape 콜백 함수 등록, reshape함수는 윈도우 처음 생성할 때와 윈도우 크기 변경시 호출된다.
        glutReshapeFunc(reshape);
        //타이머 콜백 함수 등록, 처음에는 바로 호출됨.
        glutTimerFunc(0, timer, 0);
     
        //GLUT event processing loop에 진입한다.
        //이 함수는 리턴되지 않기 때문에 다음줄에 있는 코드가 실행되지 않는다. 
        glutMainLoop();          
     
        return 0;
    }
    cs


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

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

    유튜브 구독하기


    댓글 0

Designed by Tistory.