본문 바로가기

Programming/OpenGL

OpenGL Transformations_Viewing(Camera)

옆에 부제로 카메라를 붙여 두었던 이유가 있겠죠~?

넹~ Viewing은 Camera에 관련된 거에요. 이전 포스팅들에서는 테스트를 위해서 간단한 설명들만 했지만, 이제 조금 더 들어가 봐야겠죠?(해치지 않아요 -_-*)

OpenGL에서 transformation과 viewing에 관련된 가장 중점이 되는 부분이 Camera에요. 기본적으로 OpenGL의 카메라는 z축의 음수 방향을 바라보고 있습니다. 바로 아래 처럼 말이죠.


이러한 카메라가 가지는 coordinate는 오브젝트가 가지는 coordinate와는 별개입니다.

Viewing Transformation는 장면(Scene)을 적용시키는 첫 번째 변환이며, 어디에서 어디를 바라보고 있는가를 알아야 해요.(원문에서는 aim 이라고 표현했는데, 포커스와 비슷한 의미 같아요:D)

카메라의 기본값
  • 위치(Positioned at origin) : (0, 0, 0)
  • 바라보는 방향 : -z축
카메라를 이동시키거나 회전 시키는 것들은 OpenGL이 제공하는 함수로 효과적인 viewing transformation을 할 수 있어요.

일단, 기억해야 할 가장 중요한 건! viewing transformation이 그 어떤 변환보다 선행 되어야 한다는 거에요. 이유가 eye-coordinate system이기 때문이라는 데, 이 부분에 대해서 찾아봤는데 굉장히 기본적인 내용 인가 봐요.(이런 기본적인 거도 모르고 있는 나는…?!!!) 저거에 대해서는 설명이 별도로 들어가 있지 않더라구요.(ㄱ- 끄응;;)

앞선 포스팅에서 그림을 통해서 잠깐 설명 했다시피 최종적으로 계산 되어지는 행렬 이기 때문에 먼저 OpenGL한테 보내야 하나봐요. - 라고 조심스럽게 설명을 달아봅니다 :)


그럼 어떻게 viewing transformation을 만들까요?

  • 행렬 초기화
    아래의 함수를 통해서 행렬을 초기화 할 수 있습니다.
    • 함수 원형
      void glLoadIdentity(void);
      
    • 인자
      void

    • 반환값
      void

    • 처리
      현재 처리되는 행렬을 단위행렬로 만들어 버립니다.

    이 초기화 과정을 거치게 되면, 카메라는 초기의 설정을 유지하는 행렬을 가지게 됩니다.
    viewing matrix를 초기화 시킨 상태에서 아무런 명령도 내리지 않으면, 우리는 원래 OpenGL이 가지고 있는 초기값인 (0, 0, 0) 에서 -z축을 바라보는 상태의 화면을 보게 되는 거죠.


  • 변환 행렬 정의하기
    정의 한다 라는 이름으로 제목을 짓기엔 좀 그렇지만… 가장 부합되는 단어 인거 같아요 ^^;;;
    크게 세 가지 방법으로 볼 수 있습니다.
    1. gluLookAt(..) 함수의 사용
      아마도 보통 이 함수를 가장 편하게 사용하지 않을까 싶은데요, camera에 대한 확장 함수로서 내부적으로 이동과 회전에 대한 행렬을 만들어 주는 함수에요.
      • 함수 원형
        void gluLookAt(
        	GLdouble eyex, GLdouble eyey, GLdouble eyez,
        	GLdouble centerx, GLdouble centery, GLdouble centerz,
        	GLdouble upx, GLdouble upy, GLdouble upz);
        


      • 인자
        eyex, eyey, eyez : 카메라의 위치
        centerx, centery, centerz : 카메라가 바라보는 지점
        upx, upy, upz : 카메라의 위쪽 방향

      • 반환값
        void

      • 처리
        내부적으로 viewing transformation matrix를 만들어 줍니다.

      • 예시 코드를 봐볼까요? :D 여기 있는 코드들 중 이해가 안되는 부분이 있다고 해서 좌절 하진 마세요ㅎ 나중에 계속 나오게 되는 부분들이니까요.
        void DisplayScene()
        {
        	glClear(GL_COLOR_BUFFER_BIT);	// clear the color buffer
        	glColor3f(1.0f, 0.0f, 0.0f);	// set color to red
        	glLoadIdentity();				// clear the current matrix
        
        	gluLookAt(
        		0.0f, 0.0f, 10.0f,		// current camera location (0, 0, 10)
        		0.0f, -100.0f, 0.0f,	// camera looks (0, -100, 0)
        		0.0f, 1.0f, 0.0f		// camera's up direction is (0, 1, 0) equal to y axis
        		);
        
        	glBegin(GL_TRIANGLES);
        		glVertex3f(10.0f, 0.0f, 0.0f);
        		glVertex3f(0.0f, 10.0f, 0.0f);
        		glVertex3f(-10.0f, 0.0f, 0.0f);
        	glEnd();
        
        	// flush the buffer
        	glFlush();
        }
        


    2. glTranslate*(..), glRotate*(..) 함수의 사용
      Model Transformation에서 사용하게 되는 함수 인데, 사실 오브젝트를 변환 시킬 때 사용하는 행렬의 형태는 카메라에서 사용하는 행렬의 형태와 같아요. 앞서 설명한 gluLookAt(..) 함수 또한 내부적으로 이 함수들을 이용해서 만들어 진 거라고 볼 수 있죠.

      여기서 잘 보게 되면, 보통 OpenGL 함수의 형태(gl+Function Name)와는 다르게 가운데에 뭐가 하나 들어가 있죠? "u" 바로 utility의 약자 인데요. 제가 알고 있는거로는 원래 있는 기능들이 너무 로우레벨이라서 사용에 불편함을 느낀 개인이 만든 함수 인데, 너무 많이 사용해서 언제부터인지 범용적으로 사용 했다나…('-';;; 가물가물;;)


      gluLookAt(..) 함수를 사용한 display 세팅처럼 오브젝트가 카메라로 부터 일정 거리 떨어져 보이는 대에는 두 가지 방법이 있어요. 하는 앞서 사용한 방법처럼 카메라를 뒤로 이동시키는 방법. 다른 하나는 오브젝트를 앞으로 이동시키는 방법.

      이런 utility 함수를 쓰기 싫다면 카메라를 default로 놓고, 오브젝트를 카메라가 이동한 만큼 더욱 이동시키면 되겠죠.

      void DisplayScene()
      {
      	glClear(GL_COLOR_BUFFER_BIT);	// clear the color buffer
      	glColor3f(1.0f, 0.0f, 0.0f);	// set color to red
      	glLoadIdentity();				// clear the current matrix
      
      	glTranslatef(0.0f, 0.0f, -10.0f);
      
      	glBegin(GL_TRIANGLES);
      		glVertex3f(10.0f, 0.0f, 0.0f);
      		glVertex3f(0.0f, 10.0f, 0.0f);
      		glVertex3f(-10.0f, 0.0f, 0.0f);
      	glEnd();
      
      	glFlush();
      }
      

      위쪽의 카메라 세팅과 다른점을 볼까요? 바로gluLookAt이 없어지고, glTranslatef가 들어가 있죠. 그거도 원래 카메라 위치에 (-) 만큼요. 그림으로 보면 이해가 빠르시려나.. :)


      그림이 다소 난잡 할 수 있지만, View의 이동 변환이 첫 번째 방법에 의한 거구요, Model의 이동변환이 두 번째 방법이에요. 결과적으로는 화면상에 디스플레이 되는 건 똑같이 되는 거구요 :)

      Model Matrix + View Matrix = ModelView Matrix ?!
    3. User define 루틴 만들기
      사용자가 직접 자신만의 coordinate system을 만드는 거에요(밥로슨도 아니고…:D) 예를 들면 극 좌표계(Polar coordinate system)같은거...

      약간의 공간 지각능력만 있다면 이제 나오는 예시는 쉽게 이해가 될 거에요.(물론 없다고 좌절 금지~! 저도 없으니까요 ㅠ_ㅠ)

      void PlaneView(GLfloat planeX, GLfloat planeY, GLfloat planeZ,	// the plane's position
      	GLfloat roll, GLfloat pitch, GLfloat yaw)		// orientation
      {
      	// roll is rotation aboue the z axis
      	glRotatef(roll, 0.0f, 0.0f, 1.0f);
      
      	// yaw, or heading, is rotation aboue the y axis
      	glRotatef(yaw, 0.0f, 1.0f, 0.0f);
      
      	// pitch is roation aboue the x axis
      	glRotatef(pitch, 1.0f, 0.0f, 0.0f);
      
      	// move the plane to the plane's world coordinates
      	glTranslatef(-planeX, -planeY, -planeZ);
      }
      


      비행기가 공중에서 날아가면서 임의의 장소를 바라보았을 때는 사실 지표면에 밀착해서 본다거나 (일반적으로 물구나무 하면서 걸어다니는 사람은 없으니까) 시야가 상하로 뒤집힌다거나 하는 경우에 대한 제약 같은 건 없으니까 자유자제로 화면을 본다고 했을 때의 모습이에요.

      저게 각도로 좌표를 측정하는 극 좌표계 에요. 기준으로 잡고 있는 축(x, y, z)에 대해서 각각 몇도씩 돌아간 곳의 방향을 가리키고 있느냐~ 자세한 건 구글링!ㅋㅋ

    이번 Viewing Transformation은 끝났네요 다음 파트도 보다 보면, 대략적인 느낌이 올텐데… 정점의 좌표는 상대적인거! 구지 모델과 뷰로 나눌 필요가 있나 느끼게 되지 않을까 생각해 보아요 :)

'Programming > OpenGL' 카테고리의 다른 글

OpenGL Transformation_Matrix  (4) 2012.03.22
OpenGL Transformations_Modeling  (0) 2012.03.17
Understanding Coordiante Transformations  (0) 2012.03.13
OpenGL primitives_2  (2) 2011.12.24
OpenGL primitives_1  (0) 2011.12.22