GLUT Tutorials

키 입력 예제 : 세상을 둘러 보아요~ 2 탄:)

이번 장에서는 앞장에서 만든 예제에 키입력 고급 기법을 사용해서 수정해보겠습니다. 새로 추가한 코드에는 주석을 달았습니다.

초기화 부분에 deltaAngle 과 deltaMove 라는 두 개의 변수를 추가했습니다. 이 변수들은 각각 카메라의 회전과 이동을 제어합니다. 0 이 아닐 때에는 카메라가 어떤 행동을 취하고 0 일 때에는 카메라가 고정되어 있습니다. 이 두 변수는 카메라의 초기 상태를 고정 상태로 만들기 위해서 0 으로 초기화합니다.

#include <math.h>
#include <gl\glut.h>
#include <gl\gl.h>
#include <gl\glu.h>

float angle=0.0, deltaAngle = 0.0;
float ratio;
float x=0.0f,y=1.75f,z=5.0f;
float lx=0.0f,ly=0.0f,lz=-1.0f;
GLint snowman_display_list;
int deltaMove = 0;

void changeSize(int w, int h)
{
    // 창이 너무 작아졌을때 0 으로 나뉘는 것을 방지합니다.
    if(h == 0)
        h = 1;

    ratio = 1.0f * w / h;
    // 좌표계를 수정하기 전에 초기화합니다.
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // 뷰포트를 창 전체크기로 설정합니다. 
    glViewport(0, 0, w, h);

    // 절단 공간을 설정합니다.
    gluPerspective(45,ratio,1,1000);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(x, y, z, 
            x + lx,y + ly,z + lz,
            0.0f,1.0f,0.0f);
}

void drawSnowMan()
{
    glColor3f(1.0f, 1.0f, 1.0f);

    // 몸을 그립니다.
    glTranslatef(0.0f ,0.75f, 0.0f);
    glutSolidSphere(0.75f,20,20);

    // 머리를 그립니다.
    glTranslatef(0.0f, 1.0f, 0.0f);
    glutSolidSphere(0.25f,20,20);

    // 두 눈을 그립니다.
    glPushMatrix();
        glColor3f(0.0f,0.0f,0.0f);
        glTranslatef(0.05f, 0.10f, 0.18f);
        glutSolidSphere(0.05f,10,10);
        glTranslatef(-0.1f, 0.0f, 0.0f);
        glutSolidSphere(0.05f,10,10);
    glPopMatrix();

    // 코를 그립니다.
    glColor3f(1.0f, 0.5f , 0.5f);
    glRotatef(0.0f,1.0f, 0.0f, 0.0f);
    glutSolidCone(0.08f,0.5f,10,2);
}

GLuint createDL()
{
    GLuint snowManDL;

    // 디스플레이리스트를 생성하고 id 를 반환합니다.
    snowManDL = glGenLists(1);

    // 디스플레이리스트를 시작합니다.
    glNewList(snowManDL,GL_COMPILE);

    // 렌더링을 수행하는 함수를 호출합니다.
    drawSnowMan();

    // 디스플레이리스트를 끝마칩니다.
    glEndList();

    return(snowManDL);
}

void initScene()
{
    glEnable(GL_DEPTH_TEST);
    snowman_display_list = createDL();
}

void orientMe(float ang) 
{
    lx = sin(ang);
    lz = -cos(ang);
    glLoadIdentity();
    gluLookAt(x, y, z, 
            x + lx,y + ly,z + lz,
            0.0f,1.0f,0.0f);
}

void moveMeFlat(int i)
{
    x = x + i*(lx)*0.1;
    z = z + i*(lz)*0.1;
    glLoadIdentity();
    gluLookAt(x, y, z, 
            x + lx,y + ly,z + lz,
            0.0f,1.0f,0.0f);
}

아래 함수에 추가된 코드가 있습니다. 이 함수는 각각의 카메라 액션을 뜻하는 두 개의 변수가 0 이 아닌지 검사하고 0 이 아니라면 카메라의 필요한 동작에 적절한 함수를 호출합니다.

void renderScene(void)
{
    if (deltaMove)
        moveMeFlat(deltaMove);
    if (deltaAngle)
    {
        angle += deltaAngle;
        orientMe(angle);
    }

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // 지형을 그립니다.
    glColor3f(0.9f, 0.9f, 0.9f);
    glBegin(GL_QUADS);
        glVertex3f(-100.0f, 0.0f, -100.0f);
        glVertex3f(-100.0f, 0.0f, 100.0f);
        glVertex3f( 100.0f, 0.0f, 100.0f);
        glVertex3f( 100.0f, 0.0f, -100.0f);
    glEnd();

    // 36개의 눈사람을 그립니다.
    for(int i = -3; i < 3; i++)
        for(int j=-3; j < 3; j++)
        {
            glPushMatrix();
                glTranslatef(i*10.0,0,j * 10.0);
                glCallList(snowman_display_list);;
            glPopMatrix();
        }
    glutSwapBuffers();
}

다음에 나오는 함수들은 각각 특수키의 콜백함수로 일반키가 놓였을 때 호출되는 콜백함수로 등록합니다.

void pressKey(int key, int x, int y)
{
    switch (key)
    {
    case GLUT_KEY_LEFT : 
        deltaAngle = -0.01f;
        break;
    case GLUT_KEY_RIGHT : 
        deltaAngle = 0.01f;
        break;
    case GLUT_KEY_UP : 
        deltaMove = 1;
        break;
    case GLUT_KEY_DOWN : 
        deltaMove = -1;
        break;
    }
}

void releaseKey(int key, int x, int y)
{
    switch (key)
    {
    case GLUT_KEY_LEFT : 
    case GLUT_KEY_RIGHT : 
        deltaAngle = 0.0f;
        break;
    case GLUT_KEY_UP : 
    case GLUT_KEY_DOWN : 
        deltaMove = 0;
        break;
    }
}

main 함수에는 세 줄의 코드를 추가했습니다.:

반복되는 키입력을 정지하기 위해서 glutIgnoreKeyRepeat 함수를 0 이 아닌 값을 인자로 주어 호출했고 그 다음에 glutSpecialUpFunc 와 glutKeyboardUpFunc 함수로 콜백함수를 등록했습니다.

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(640,360);
    glutCreateWindow("SnowMen from 3D-Tech");

    initScene();

    glutIgnoreKeyRepeat(1);
    glutKeyboardFunc(processNormalKeys);
    glutSpecialFunc(pressKey);
    glutSpecialUpFunc(releaseKey);

    glutDisplayFunc(renderScene);
    glutIdleFunc(renderScene);

    glutReshapeFunc(changeSize);

    glutMainLoop();

    return(0);
}

VC 6.0 프로젝트 파일 을 받아서 카메라 설정 함수들을 카메라 설정 함수들을 가지고 놀아보세요 :)