Software Development/Graphics

gluLookAt() 함수 구현 설명

huiyu 2018. 6. 24. 13:02

gluLookAt()

 : view transform matrix를 정의

 - 시점 좌표계를 정의하는 함수로, (eyeX, eyeY, eyeZ)에 있는 카메라가 (centerX, centerY, cneterZ)에 있는 초점을 바라보는 것이다.
 - (upX, upY, upZ)는 카메라 상향 벡터이다.

1
2
3
4
5
6
7
8
9
10
11
12
void gluLookAt(    
GLdouble eyeX,
     GLdouble eyeY,
     GLdouble eyeZ,
     GLdouble centerX,
     GLdouble centerY,
     GLdouble centerZ,
     GLdouble upX,
     GLdouble upY,
     GLdouble upZ
);
 
cs


Parameters

 - eyeX, eyeY, eyeZ : 눈의 위치(카메라의 위치)
 - centerX, centerY, centerZ : 카메라의 초점(참조 위치)
 - upX, upY, upZ : 카메라의 위쪽벡터 방향 지정(x가 1이면 x축으로 누워있고, y가 1이면 y축을 중심으로 세워져있다.)



gluLookAt함수 구현(Tizen DALi 기반)

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
{
Vector3 Eye  = Vector3( 0.0-100.0100.0);
Vector3 At = Vector3(0.00.00.0);
Vector3 UpVector  = Vector3(0.01.00.0);
 
MyLookAt(Eye, At, UpVector);
}

void MyLookAt(Vector3 Eye, Vector3 At, Vector3 UpVector)
{
    Vector3 forward = Eye-At;
    forward.Normalize();

    Vector3 side = UpVector.Cross(forward);
    side.Normalize();

    Vector3 up = forward.Cross(side);

    Vector3 pos(-Eye.Dot(side), -Eye.Dot(up), -Eye.Dot(forward));
    
float inpVM[] = { 
side.x,  -up.x,  forward.x,  0.0,
side.y,  -up.y,  forward.y,  0.0
side.z,  -up.z,  forward.z,  0.0
pos.x,   pos.y,  pos.z,  1.0 
};
    Matrix viewMatrix = Matrix(inpVM);
}
cs

위 함수를 이해하기 위해선 벡터의 외적과 내적 보기 -> http://huiyu.tistory.com/300

1. forward vector 구하기

  forward = Eye - At; // forward는 카메라가 바라보는 방향이기 때문.
  forward.Normalize(); // 정규화


2. eye side vector 구하기

side = UpVector.Cross(Forward) //UpVector와 Forward벡터 외적
 -> 두 벡터의 외적곱은, 두 벡터가 이루는 평면에 수직인 벡터를 만든다. 
   즉, 위쪽을 가리키는 UpVector(0,1,0)과 카메라가 가리키는 시점을 의미하는 Forward Vector가 이루는 평면에 수직인 벡터. Side 벡터를 계산한다.

 side.Normalize();// 정규화

3. eye up vector 구하기

 - 카메라 기준의 up벡터를 구한다.
 up = Forward.Cross(Side)
 -> Forward와 Side 벡터의 외적, 두 벡터가 이루는 평면에 수직인 벡터인 up 벡터를 구한다.

 up.Normalize(); //마찬가지로 정규화

계산으로 구한 forward, side, up 벡터는 전역 좌표계 상의 카메라 방향을 의미한다.
이를 행렬로 적용하면 아래와 같다. 이는 카메라(eye)를 기준으로 at방향을 가리키고 있는 매트릭스이다.

1
2
3
4
5
6
float inpVM[] = { 
          side.x, -up.x,   forward.x,  0.0,
          side.y, -up.y,   forward.y,  0.0
          side.z, -up.z,   forward.z,  0.0
          0,          0,           0,  1.0 
    };
cs

카메라는 다시 구해놓은 원점에서부터 특정 위치만큼 떨어져 있다-> eye좌표
카메라의 -좌표만큼 이동 연산을 해주면 된다.

1
2
3
4
5
6
7
8

 
float TM[] = { 
          1.0,     0.0,   0.0,   0.0,          
          0.0,     1.0,   0.0,   0.0,         
          0.0,     0.0,   1.0,   0.0,           
          Eye.x, Eye.y, Eye.z,   1.0
    };
cs

ViewMatrix = inpVM X TM의 연산을 해주면, 뷰 매트릭스값을 구할 수 있다.

결국, 두 연산의 곱은 Eye의 각 방향에 대한 내적 곱이 된다.

1
2
3
4
5
6
7
8
Vector3 pos(-Eye.Dot(side), -Eye.Dot(up), -Eye.Dot(forward));

float inpVM[] = { 
          side.x, -up.x,   forward.x,  0.0,
          side.y, -up.y,   forward.y,  0.0
          side.z, -up.z,   forward.z,  0.0
          pos.x,  pos.y,       pos.z,  1.0 
    };
cs

*이제 공간상의 물체에 이 ViewMatrix값을 적용하면, 카메라의 시점을 기준으로 물체의 변환 결과를 얻을 수 있다.


참조
https://m.blog.naver.com/PostView.nhn?blogId=utez&logNo=90115780711&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F
https://www.khronos.org/opengl/wiki/GluLookAt_code
https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluLookAt.xml
http://zamezzz.tistory.com/66
http://celdee.tistory.com/543
*승호님이 작성해주신 코드!

728x90