04. 회전


소개



안녕하세요. 이 튜토리얼에서 저는 여러분에게 삼각형과 사각형을 회전하는 방법에 대해서 설명할까 합니다.삼각형은 Y축 상에서, 사각형은 X축상에서 회전을 할 것입니다. 이 강좌에서는 새로운 2개의 변수가 추가되었습니다. rtri는 삼각형의 각도, rquad는 사각형의 각도를 저장합니다.

폴리곤으로 구성된 장면을 만드는 것은 쉽습니다. 이 물체에 움직임을 더하면 장면이 살아 움직이게 됩니다. 축이 아닌 화면상의 한 점 주위로 물체를 회전시키는 방법은 다른 강좌에서 다룰 것입니다.














본문


저번 강좌에서는 저는 여러분에게 삼각형과 사각형에 색을 입히는 방법에 대해서 설명했습니다. 이 강좌에서는 색이 입혀진 물체들을 한 축 주위로 회전시키는 방법에 대해서 알아보겠습니다.

저희는 저번 튜토리얼의 코드에 약간의 코드를 추가할 것입니다. 바뀐 부분의 코드부분을 아래에 모두 다시 작성하여 추가된 것이 무엇인지, 그리고 어떤 부분을 바꿔야하는지를 알아보기 쉽게 하였습니다.

자, 그럼 시작해볼까요? 각 물체의 회전각을 저장할 두 변수부터 추가해 봅시다. 변수를 추가할 위치는 프로그램의 젤 윗부분 중 다른 변수들 바로 아래입니다. 'bool fullscreen=TRUE;' 바로 아랫에 새로운 2줄이 보이시죠? 이 라인들은 2개의 부동소수점 변수를 정의합니다. 저희는 이 두 변수를 이용하여 물체를 매우 미세한 정확도로 회전시킬 것입니다. 부동소수점은 소수점 이하의 수를 사용할 수 있게 해줍니다. 따라서 각도를 반드시 1, 2, 3 등의 정수로 표현해야 하는 것이 아니라 1.1, 1.7, 2.3, 심지어는 1.015처럼 세세하게 조절할 수 있습니다. 여러분은 곧 OpenGL 프로그래밍에서 부동소수점 수가 필수적이라는 사실을 발견하시게 될 것입니다. 새로운 변수들은 삼각형을 회전시키는 rtri와 사각형을 회전시키는 rquad입니다.

#include    <windows.h>                    // 윈도우즈용 헤더파일
#include    <gl\gl.h>                      // OpenGL32 라이브러리용 헤더파일
#include    <gl\glu.h>                     // GLu32 라이브러리용 헤더파일
#include    <gl\glaux.h>                   // GLaux 라이브러리용 헤더파일

HDC        hDC=NULL;                       // GDI 장치 컨텍스트
HGLRC        hRC=NULL;                     // 렌더링 컨텍스트
HWND        hWnd=NULL;                     // 우리의 윈도우 핸들을 기억
HINSTANCE    hInstance;                    // 응용프로그램의 인스턴스를 기억

bool        keys[256];                     // 키보드 루틴에 사용하는 배열
bool        active=TRUE;                   // 윈도우 활성여부 플래그
bool        fullscreen=TRUE;               // 전체화면 플래그. 디폴트 값은 TRUE

GLfloat        rtri;                       // 삼각형의 각도 ( 새코드 )
GLfloat        rquad;                      // 사각형의 각도 ( 새코드 )


이제부터 우리는 DrawGLScene() 코드를 수정해야 합니다. 이 함수의 전체 프로시저를 아래에 다시 표현할것입니다.이는 원래 코드에서 어떤 점들이 바뀌었는지를 보기 편하게 하기 위함입니다. 수정을 한 이유와 새로운 코드들이 하는 일이 정확히 무엇인지를 설명드리겠습니다. 다음의 코드 부분은 이전 튜토리얼의 것과 동일합니다.
 
int DrawGLScene(GLvoid)                        // 모든 드로잉을 처리하는 곳
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // 화면과 깊이 버퍼를 지움
   glLoadIdentity();                    // 뷰를 리셋
   glTranslatef(-1.5f,0.0f,-6.0f);                // 화면 안쪽과 왼쪽으로 이동



다음은 새로운 코드라인입니다. glRotatef(Angle,Xvector,Yvector,Zvector)는 한 축의 주위로 물체를 회전시킵니다. 앞으로 이 명령어를 자주 사용하시게 될 것입니다. 각도는 물체를 어느정도 회전시킬 것인지를 나타내는 어떤 값으로써 보통 변수안에 저장합니다. Xvector, Yvector, Zvector 인자들은 회전의 축이 되는 벡터를 나타냅니다. 여러분이 (1,0,0)의 값을 사용하면 이것은 x축을 따라 오른쪽으로 1단위 방향으로 이동하는 벡터를 나타냅니다. 마찬가지로 (-1,0,0)의 값은 역시 x축을 따라 1단위의 방향만큼 이동하는 벡터를 나타내지만 이번에는 오른쪽이 아니라 왼쪽이 됩니다.

D. Michael Traub님이 위의 Xvector, Yvector, Zvector 인자에 대한 설명을 제공해 주셨습니다.

X, Y, Z 회전에 대한 이해를 돕기 위해 다음의 예를 들어 설명하겠습니다.

X 축 - 자, 여러분이 바람개비를 돌린다고 가정해봅시다. 바람개비를 측면에서 바라보면 바람개비를 고정하는 핀이 눈에 수평으로 보이지요. 이것이 바로 OpenGL의 x축입니다. 바람개비는 x축(고정핀) 주위로 회전하고, 바람이 부는 방향에 따라 바람개비가 회전하는 방향이 다를 것입니다. OpenGL에서는 바람개비가 오른쪽에서 왼쪽으로 또는 왼쪽에서 오른쪽으로 회전하게 됩니다. 저희가 OpenGL의 x축 상에서 무언가를 회전시키면 이와 같은 방법으로 회전할 것입니다.

Y 축 - 자, 여러분이 풀밭 가운데 서있다고 상상해봅시다. 여러분을 향해 돌진하는 커다란 토네이도가 있습니다. 토네이도의 중심은 하늘로부터 지면으로 이동합니다(위와 아래. OpenGL에서 y축과 비슷한 이치임). 토네이도 안에 있는 흙먼지와 잡동사니들은 y축(토네이도의 중심) 주변을 왼쪽->오른쪽 또는 오른쪽->왼쪽으로 회전합니다.

Z 축 - 자, 여러분은 선풍기의 앞면을 바라보고 있습니다. 선풍기의 중앙은 여러분 또는 여러분에서 멀어지는 쪽을 가르킵니다(OpenGL의 z축입니다). 선풍기의 날개들은 z축(선풍기의 중앙) 주위를 시계방향 또는 시계반대방향으로 회전합니다. OpenGL의 z축 상에서 무언가를 회전시키면 이와 마찬가지 방법으로 회전하게 됩니다.

이제 다음 코드라인에서 rtri가 7이면 Y 축상에서 왼쪽->오른쪽으로 7만큼 회전을 하게 됩니다. 이 코드를 이리저리 바꿔보면서 여러가지 실험을 해보십시요. 0.0f를 1.0f로 바꾸고 1.0f를 0.0f로 바꾸면 삼각형을 X와 Y축에서 동시에 회전할 수 있습니다.

회전은 호도법이 아닌 각도를 사용합니다. rtti가 10의 값을 가지면 삼각형은 y축 주변을 10도 회전할 것입니다.

glRotatef(rtri,0.0f,1.0f,0.0f);                // Y축 상에서 삼각형을 회전함(새코드)

다음 코드 부분은 변경되지 않았습니다. 이것은 색상이 부드럽게 혼합되는 삼각형 하나를 그립니다. 이 삼각형은 화면의 왼쪽에 그려질 것이며, Y축 상에서 왼쪽에서 오른쪽으로 회전을 할 것입니다.
 
   glBegin(GL_TRIANGLES);                    // 삼각형을 그리기 시작
       glColor3f(1.0f,0.0f,0.0f);            // 삼각형의 윗점을 빨강색으로
       glVertex3f( 0.0f, 1.0f, 0.0f);            // 삼각형의 첫번째 점
       glColor3f(0.0f,1.0f,0.0f);            // 삼각형의 왼쪽 점을 녹색으로
       glVertex3f(-1.0f,-1.0f, 0.0f);            // 삼각형의 두번째 점
       glColor3f(0.0f,0.0f,1.0f);            // 삼각형의 오른쪽 점을 파랑색으로
       glVertex3f( 1.0f,-1.0f, 0.0f);            // 삼각형의 세번째 점
   glEnd();                        // 삼각형 그리기를 마침


아래코드에서 glLoadIdentity()가 하나 더 추가된 모습을 보실 수 있으실 것입니다. 이는 뷰를 리셋하기 위해서입니다. 뷰를 리셋하지 않으면 물체가 회전된 뒤에 평행이동을 하게 되므로 예상치 않은 결과를 얻게 될 것입니다. 일단 회전을 한 축은 저희가 생각하는 방향을 향하고 있지 않을 수도 있기 때문입니다. 따라서 X축 상에서 왼쪽으로 이동하면 각 축에서 회전을 가한 양에 따라 그 결과가 위로 또는 아래로 이동할 수도 있는 것입니다. 제가 말씀드린것이 잘 이해되지 않으시는 분들은 glLoadIdentity() 라인을 뺀체 프로그램을 실행해보십시오. 그러면 무슨 뜻인지 아실 수 있을 것입니다.

일단 장면이 리셋되었다면 X가 왼쪽에서 오른쪽으로, Y는 위와 아래, Z는 안쪽과 바깥쪽을 향하니 우리는 평행이동을 할 수 있습니다. 이전 강좌하고 틀려진 점이 있다면 오른쪽으로 이동하는 양이 3.0이 아니라 1.5라는 것입니다. 저희가 화면을 리셋할 때 기준점이 화면의 중앙으로 이동하였기 때문입니다. 즉, 저희는 더이상 화면 왼쪽으로 1.5단위에 있지 않고, 0.0으로 돌아와 있는 것입니다. 따라서 영점으로부터 1.5만큼 오른쪽으로 이동하려면 왼쪽에서 중점으로 1.5를 이동한 뒤 다시 오른쪽으로 1.5만큼(따라서 총 3.0) 이동할 필요가 없고  중점에서 오른쪽으로 1.5 단위만큼만 이동하면 되는 것입니다.

화면 오른쪽의 새로운 장소로 자리를 옮긴 뒤에는 사각형을 X축 주위로 회전시킵니다. 이렇게 하면 사각형을 위/아래로 회전시키게 됩니다.

 
   glLoadIdentity();                    // 현제 모델뷰 행렬을 리셋함
   glTranslatef(1.5f,0.0f,-6.0f);                // 오른쪽으로 1.5단위 화면속으로 6.0단위만큼 이동함
   glRotatef(rquad,1.0f,0.0f,0.0f);            // X축 주위로 사각형을 회전시킴(새코드)


다음의 코드 부분은 예전과 변함이 없습니다. 이것은 파란색의 사각형 하나를 화면 오른쪽에 그립니다. 단 이번에는 회전이 되어있겠죠?

   glColor3f(0.5f,0.5f,1.0f);                // 멋진 파란색으로 색상을 지정
   glBegin(GL_QUADS);                    // 사각형 그리기 시작
       glVertex3f(-1.0f, 1.0f, 0.0f);            // 좌상점
       glVertex3f( 1.0f, 1.0f, 0.0f);            // 우상점
       glVertex3f( 1.0f,-1.0f, 0.0f);            // 우하점
       glVertex3f(-1.0f,-1.0f, 0.0f);            // 좌하점
   glEnd();                        // 사각형 그리기 마침

다음의 두 라인은 새로 추가된 코드입니다. rtri와 rquad를 컨테이너(보관함)이라고 생각해 보십시오. 저희는 프로그램의 시작부분에서 이 보관함들을 만들었습니다(GLfloat rtri와 GLfloat rquad). 이 컨테이너들을 만들 때 그 안에는 아무것도 들어있지 않습니다. 아래에 있는 첫번째 라인은 이 보관함에 0.2를 '''더합니다'''. 따라서 이 코드섹션 이후, rtri 컨테이너에 있는 값을 검사한다면 이는 0.2만큼 증가해있을 것입니다. rquad 컨테이너는 0.15만큼 감소합니다. 따라서 rquad 보관함에 있는 값을 검사할 때마다 이 값은 0.15만큼 줄어들어 있을 것입니다. 값을 감소시키면 수를 증가시킬 때와는 반대방향으로 그 물체가 회전을 하게 됩니다.

아래의 코드에서 +를 -로 바꿔보면서 물체가 다른 방향으로 회전하는 방법을 살펴보시기 바랍니다. 값을 0.2에서 1.0으로 바꿔보는 것도 좋을 것입니다. 이 값이 커지면 커질수록 물체는 더욱 빨리 회전을 하게 됩니다. 당연히 작은 값은 회전속도를 늦춥니다.
 
   rtri+=0.2f;                        // 삼각형의 회전변수를 증가(새코드)
   rquad-=0.15f;                        // 사각형의 회전변수를 감소(새코드)
   return TRUE;                        // 계속 진행
}


마지막으로 창의 윗부분에 올바른 제목을 보이도록 창모드 / 전체화면 모드를 전환하는 코드를 수정합시다.

 
           if (keys[VK_F1])            // F1이 눌렸는지 확인
           {
               keys[VK_F1]=FALSE;        // 눌린 경우 그 키를 FALSE로 만듬
               KillGLWindow();            // 현재 창을 죽임
               fullscreen=!fullscreen;        // 전체화면 / 창모드를 전환
               // OpenGL 창을 다시 만듬 ( 수정된 코드 )
               if (!CreateGLWindow("NeHe의 회전 튜토리얼",640,480,16,fullscreen))
               {
                   return 0;        // 창을 만드는데 실패했다면 종료
               }
           }


저는 본 강좌에서 물체를 한 축 주변으로 회전시키는 방법을 가능한 자세히 설명하려고 노력했습니다. 코드를 이리저리 변경하면서 결과물을 살펴보시길 바랍니다.X, Y, Z축 상에서 또는 모든 세 축상에서 동시에 물체를 회전시켜 보시는 것도 좋을듯 싶습니다. 이 강좌에 대한 의견이나 질문이 있으신 분들은 제게 이메일을 보내주십시요. 만약 제가 잘못 설명을 한 부분이 있거나 코드 일부분을 더 좋게 개선할 여지가 있다고 생각하시는 분들도 역시 제게 알려주십시요. 저는 힘닿는한 최고의 OpenGL 튜토리얼을 만들고 싶습니다. 따라서 여러분의 피드백은 저에게 매우 소중하답니다.

소스코드 다운로드


이 강좌의 소스코드를 다운받으실 수 있습니다. 자신의 환경에 맞는 파일을 받아 사용하세요.

원문 정보

  • 저자: Jeff Molofee (NeHe)
  • 원문보기: Lesson 04

번역문 정보


현재 상태

  • 초벌번역시작 (2005년 8월 15일)
  • 초벌번역완료 (2005년 8월 18일)
  • 재벌및 감수 시작(2005. 8. 19)
  • 재벌및 감수 완료(2005. 8. 19)
Comments