OpenGL

[OpenGL-10] object viewer 구현하기 (2)

zamezzz 2017. 5. 17. 01:49

 Object Viewer 구현하기 (2)



안녕하세요.


오늘은 지난포스팅에 이어 obj viewer 구현하기 두번째 포스팅을 진행하겠습니다.


지난 포스팅에서는 obj파일로 표현된 객체를 구현하고, 이를 화면 중앙에 적절한 크기로


위치시키는 것 까지 진행하였습니다.


오늘은 지난 포스팅에서 말씀드린 것 처럼 구체화된 오브젝트를 조명, 모델 효과를 통해


좀 더 이쁘게(?) 만드는 것에 대한 내용입니다. 


카메라, 조명, 재질, 콜백함수 이렇게 4가지 효과를 적용하여 그럴싸하게 만들어봅시다.


그럼 시작해보겠습니다.


1. 카메라(Camera)


첫 번째는 카메라입니다. 화면에 나타내는 방법은 크게 2가지가 있죠.


객체를 카메라의 view 내로 움직이는 방법과 카메라를 객체를 향해 움직이는 방법입니다.


여기서는 카메라의 여러 벡터를 이용하여 원근 투영을 구현하고자 합니다.


앞의 포스팅에서 설명드린 카메라 기법 중 원근 투영 기법이 있을텐데요.


myPerspective라는 함수를 만들어 원근 투영을 구현하겠습니다.


아래 그림을 보시면 기억이 새록새록 떠오를까요... ? :3 한번 보시죠


원근 투영 카메라의 요소를 설명해 둔 그림입니다. 보다 자세히 설명이 되어 있네요.

(출처 : http://www.ntu.edu.sg/home/ehchua/programming/opengl/cg_basicstheory.html)


여기서 보시는 것과 같이 원근 투영을 구현하기 위해서는 4개의 요소가 필요합니다.

- angle (fovy)

- aspect

- zNear

- zFar


이 4가지 요소를 통해 원근 투영을 구현하고, 여기에 언힌징(unhinging)을 적용한다면 


우리가 원하는 결과를 얻을 수 있습니다. 코드와 함께 보시죠.


mat4 myPerspective(float angle, float aspect, float zNear, float zFar) {

    mat4 V(1.0f);    


    float radian = angle * 3.14159 / 180.f;

    float h = 2 * zFar * tan(rad/2);

    float w = aspect * h;

    float c = -zNear / zFar;


    mat4 S = Scale(2/w, 2/h, 1/zFar);


    mat4 Mpt(1.0f)

    Mpt[2] = vec4(0, 0, 1/(c+1), -c/(c+1));

    Mpt[3] = vec4(0, 0, -1, 0);


    V = Mpt * S;

    return V;

}


생각보다 복잡하지만 간단한 코드입니다.


원근과 언힌징 두 부분으로 나누어 본다면 더욱 간단하게 느껴질 수 있습니다.


위의 S행렬이 원근투영을 구현한 부분이고, Mpt가 언힌징을 구현한 행렬입니다.


그리고 이 둘을 계산하면 우리가 원하는 원근투영이 완성되는 것이죠.


코드의 각 계산식을 유도하는 것은 앞의 포스팅에 그림과 함께 설명하였으니 


참고하시면 되겠습니다. 위 그림과 함께 보시면 이해가 편하리라 믿습니다.




2. 콜백 함수(callback function)


두 번째는 콜백함수 부분입니다. 


먼저 콜백 함수에 대해서 간단히 설명드리자면... 


'사용자의 입력이 있을 때 수행 할 동작을 정의한 함수' 라고 할 수 있습니다.


우리가 어떠한 입력(키보드, 마우스 등)을 할 때 뭔가 동작하는 함수들이죠.


openGL에서 제공하는 콜백함수는 GLUT(openGL Utility Toolkit)에 정의되어있습니다.


많은 종류가 있지만, 여기서는 idle, keyboard, mouse, reshape만 사용하겠습니다.


함수 이름만 봐도 무슨 역할을 하는지 아시겠죠?


-idle : 객체를 움직입니다. 애니메이션과 같이 일정 움직임을 반복시킬 때 사용해요.

-keyboard : 키보드 입력으로 객체를 제어할 때 사용

-mouse : 마우스 입력으로 객체를 제어할 때 사용

-reshape : 창(window)의 크기를 바꿀 때마다 발생하는 동작을 정의합니다.


하나하나씩 살펴보겠습니다.


 idle callback


void idle() {

    if(start==true) {

        if(axis==0) { //x axis

    Ltime[0] += 1.0;

}

else if(axis==1) { //y axis

    Ltime[1] +=1.0;

}

else if(axis==2) { //z axis

    Ltime[2] +=1.0;

}

    }


    rotx = RotateX(Ltime[0]);

    roty = RotateY(Ltime[1]);

    rotz = RotateZ(Ltime[2]);


    rot = rotx * roty * rotz;


    glutPostRedisplay();

}


start가 true일 경우 객체를 회전시킵니다. 이는 이후 키보드로 제어합니다.


마찬가지로 x,y,z축으로 회전축을 설정하는 것은 마우스로 제어할 예정입니다.


위 코드는 간단하죠? 시간(time)에 따라 각 축을 기준으로 객체를 회전합니다.


 keyboard callback


void Keyboard(unsigned char KeyPressed,int X,int Y) {

    switch(KeyPressed)

    {

case 32: //space = start/stop

    if(start==false) {

start=true;

    }

    else {

start=false;

    }

    break;

}

glutPostRedisplay();

}


위의 idle callback을 제어하기 위한 키보드 콜백함수입니다.


space키(값은 32)를 눌러서 false이면 start를 시키고, 반대의 경우 stop합니다.


이와 같은 경우로 case에 원하는 키를 입력하여 다른 키보드 콜백 함수를 구현할 수


있습니다. 예를 들어 case 'q':에 프로그램을 종료하는 코드를 넣을 수 있겠죠


 mouse callback


void mouse(int button, int state, int x, int y)  {

if(state == GLUT_DOWN) {

    switch(button) {

case GLUT_LEFT_BUTTON:         //Left button = x axis

axis=0;

break;

case GLUT_MIDDLE_BUTTON:        //Middle button = y axis

axis=1;

break;

case GLUT_RIGHT_BUTTON: //Right button = z axis

axis=2;

break;

}

}

}


다음은 mouse callback입니다. 마찬가지로 위의 idle callback의 회전축을


제어하는 기능을 합니다. 마우스의 3개 버튼을 각 축으로 설정하였습니다.


 reshape callback


void reshape(int w, int h)

{

glViewport(0, 0, w, h);


g_aspect = w/float(h);

glutPostRedisplay();

}


마지막으로 reshape callback입니다.


이는 창(window)이 변할 때 마다 일어나는 행동으 정의해둔 함수입니다.


여기서는 w와 h를 입력받아 창의 비율에 맞게 객체 또한 변환되도록 하였습니다.


직접 설정해서 창을 줄였다 늘려보면 어떤 기능인지 바로 아실겁니다.




오늘 object viewer (2) 포스팅은 여기서 마치겠습니다.


이쁘게 객체를 꾸미는 부분을 한번에 하려니... 생각보다 길어지네요.


다음 세번째 포스팅에서는 재질과 조명에 대해 정리하고 마무리하겠습니다.


그럼 이만 오늘은 포스팅을 마칠게요. 긴 글 읽어주셔서 감사합니다. 

반응형

'OpenGL' 카테고리의 다른 글

[OpenGL-11] object Viewer 구현하기 (3)  (0) 2017.05.27
[OpenGL-9] object viewer 구현하기 (1)  (13) 2017.04.06
[OpenGL-8] Lighting  (0) 2017.03.16
[OpenGL-7] Projection Matix  (0) 2016.12.31
[OpenGL-6] Model View Matrix  (2) 2016.11.13