-
[컴퓨터 그래픽스] Screen-space Object Manipulation컴퓨터그래픽스 2024. 2. 16. 13:51
잡설 없이 바로 고고
1. 물체 선택
게임을 하면서 마우스나 손가락으로 스크린 상의 물체를 선택하고, 이를 움직이는 것은 굉장히 흔한 일이다.

스크린 상에서 마우스로 클릭을 하면 당장 알 수 있는 정보는 선택된 점의 2차원 좌표(x,y)이다. 이를 이용해 클릭한 위치에 있는 물체를 찾는 기법을 다룬다.

마우스 커서의 위치가 주어지면 우리는 시작점이 (x, y, 0)이고, 방향 벡터가 (0, 0, 1)인 광선(ray)을 정의할 수 있다. 이 광선과 물체가 교차하는지 검사하면 물체를 선택할 수 있다. 그러나 스크린 공간에는 물체에 대한 정보가 없기 때문에 정의된 광선을 오브젝트 공간까지 역으로 변환하여 그 공간에서 광선과 물체가 교차하는지 검사한다. ( 이 무슨 개노가다란 말인가..)
2. 스크린 공간에서 카메라 공간까지
먼저 스크린 공간의 ray를 카메라 공간까지 가져가 보도록 하자.


위 그림은 카메라 공간에서 부터 스크린 공간까지의 변환을 보여준다. 다시 말하지만, 우리는 스크린 공간에서의 ray를 카메라 공간까지 변화시켜야 한다. 그 작업을 위해 카메라 공간에서의 광선을 (Xc, Yc, -n) 이라 정의한다. (스크린 공간에서의 점은 (Xs, Ys) 이라 하자)

위 식에서 첫째 줄은 우리가 카메라 공간에서 정의한 광선에 투영 행렬을 적용한 것이고 원근 나눗셈까지 하여 NDC로 가져온 것이다, 두번째 줄은 뷰포트 변환으로 NDC 공간에 있는 광선을 스크린 공간에서의 광선으로 변화시킨 것이다. 그 결과는 (Xs, Ys, 0)과 같다
이 결과를 다시 (Xc, Yc, -n) 에 대해 정리하면 다음과 같다.

위 결과는 카메라 공간에서의 시작점을 구한 것이고, 이제 카메라 공간에서 방향 벡터는 어떻게 되는지 살펴보자.

카메라 공간 광선의 시작점을 얻었으므로 이를 이용해 계산할 수 있다. 카메라 공간의 벡터를 뒤로 늘리면 결국 원점(카메라)에 닿을 것이므로 원점과 광선의 시작점을 연결한 벡터가 곧 방향벡터이다.
3. 스크린 공간에서 오브젝트 공간까지.
2번과 살짝 원리로 또 스크린 공간에서 정의된 ray를 오브젝트 공간까지 보내준다. 스크린 공간에서 카메라 공간까지 ray를 보낼때는 먼저 카메라 공간에서 ray를 정의한 다음 이를 스크린 공간까지 변환시켜 이를 다시 카메라 공간에서의 ray에 대해 정리하는 방식으로 ray를 구했다.
이번엔 역행렬을 사용한다.

먼저 뷰 변환의 역행렬이다. 보는 바와 같이 매우 간단하다. 위 행렬은 카메라 공간 광선을 월드 공간으로 변환시킨다. 그 다음 월드 공간에서 오브젝트 공간으로의 역행렬을 적용하게 되는데, 각각의 물체는 서로 다른 오브젝트 공간을 가지고 있음에 주의하자. 구의 월드변환의 역행렬을 주전자에 적용하면 안된다는 말이다.

광선을 매개변수 방정식으로 표현하면 위와 같다. 그런데, 우리가 이제까지 사용한 예시에서 구와 오브젝트의 s(시작점)와 d(방향벡터)는 다르다. 이는 아까도 설명했듯이 월드 공간에서 오브젝트 공간으로의 변환이 제각각이기 때문이다. 그렇다면 구와 주전자중, ray는 어떤 것을 선택해야 하는가?
4. 광선과 바운딩 볼륨 간 교차 검사
원래는 물체의 모든 polygon mesh에 대해 교차 검사를 시행하여 하나 이상의 삼각형과 교차한다면 ray가 물체를 지나는 것으로 판명할 수 있다. 그러나 상상만으로도 정말 빡센 작업이라는 것이 느껴진다 ㅎㅎ. 그래서 그래픽스 분야에서는 바운딩 볼륨(bounding volume) 이라는 기법을 사용한다. 물체의 모든 mesh를 감싸는 영역을 만들어 이를 광선의 교체 검사에 사용하는 것이다. 수업 시간에는 polygon mesh를 이용한 교차 검사 방법론 또한 배웠는데, 실제 게임에서는 잘 쓰이지 않기도 하고, 위에 언급했듯이 효율적인 방법도 아니므로 정리하지 않는다. 물론 더 정확하긴 하다. 하지만 너무 정확한 것은 때론 독이 될 때가 있는 법이다. 게임을 플레이 할 때 물체를 집어야 하는데 아주 미세한 차이로 인해 교차가 일어나지 않아서 물체가 잡히지 않는다면 너무 화가 날 것이다 ㅋㅋ. 바운딩 볼륨의 장점은 이런 측면에서도 드러나는 것 같다.

대표적인 바운딩 볼륨 2가지 이다. 왼쪽은 AABB(aixs-aligned bounding box)라 부르고, 오른쪽은 그냥 바운딩 구라 한다.

그림에서 (B)는 AABB기법, (c)와 (d)는 바운딩 구 인데, c가 d보다 조금 더 느슨한 것을 볼 수 있다. c의 경우 AABB를 이용해 계산한 것인데, 필요 이상으로 너무 넓은 범위를 차지한다. d와 같이 최적화된 구를 구하는 알고리즘은 이미 개발되어 있다고 하는데, 책에는 소개돼있지 않다. 나중에 한번 찾아서 정리해야 겠다.

한 가지 주의할 점이 있다. 우리 구하고자 하는 것은 물체와 바운딩 구가 교차하는지, 아닌지에 대한 여부이지 정확한 교차점이 아니다. 때문에 광선과 mesh의 교차점과 광선과 바운딩 볼륨의 교차점은 당연히 다를 수 있다.
바운딩 구는 구의 방정식으로 표현된다. 또한 3차원 광선은 위에서 설명한 것과 같이 매개변수 방정식으로 표현할 수 있다. 이를 이용하여 판별식을 세우면 다음과 같은 결과르 얻는다


고등학교 수학을 열심히 했다면..^^ 위 그림만 보고도 이해가 갈 것이라 생각한다.
여기서 t의 값을 이용해 구와 주전자 중 어느 물체가 먼저 부딫히는지 판별할 수 있다. t의 값이 작을수록 더 먼저 부딫히는 것인데, 광선은 처음으로 교차한 물체를 선택하게 된다.
5. 물체 회전
이제까지의 복잡한 과정을 마쳤으면, 이제 ray와 교차된 물체를 회전시킬 일만 남았다.

그림과 같이 스크린에서 물체를 터치해서 회전시켰다고 생각해보자. 효율적인 회전을 위해서 W X H 터치스크린을 2 X 2 크기의 정사각형으로 바꾼다.

스크린에서의 원점은 왼쪽 아래이고, 정사각형에서의 원점은 사각형의 중간이다. 때문에 이에 맞게 좌표가 바뀐다.
정사각형 뒤에는 2X2X2 크기의 구가 있는데 이를 아크볼(Arcball)이라 한다. 스크린에서 움직이는 손가락은 이 아크볼을 회전시키고, 그만큼 물체도 따라서 회전하게 된다.
위 그림에서 qi를 -z축을 따라 아크볼 표면에 투영하고, 마찬가지로 qi+1 또한 아크볼 평면으로 투영시켜보자. 그러면 다음과 같은 그림을 얻을 수 있다.

vi와 vi+1은 각각 qi와 qi+1으로부터 투영된 아크볼 위의 점들을 아크볼의 중심(원점)과 연결한 벡터이다. v벡터들과 수직인 회전축을 정의하고, 두 v 벡터 사이의 회전각을 정의하면 우리는 회전을 구현할 수 있다.
오른쪽 그림을 자세히 보자. 우리가 스크린 상에서 손가락이나 마우스를 올렸을 때의 점은 투영시 무조건 아크볼 위에 있지 않을 수 있다. 이때는 qx,와 qy를 정규화 하여 2차적으로 투영시키면 된다.

여기가 좀 중요하다.
아크볼 기법을 통해 회전축과 회전각이 정의되면 GPU 파이프라인을 통해 바로 스크린에 쏴줘야 한다. 때문에 이 회전축은 오브젝트 공간에서 정의되야 한다. 회전각은 스칼라 값이므로 그냥 오브젝트 공간에서 사용할 수 있다.
아크볼 공간은 GPU파이프라인에 존재하는 공간이 아니기 때문에 아까 우리가 ray를 오브젝트 공간까지 변화시킨것과 같은 방법을 사용할 수 없다. 때문에 그냥 아크볼 공간의 회전축을 그대로 카메라 공간으로 옮긴다. 즉 회전축을 카메라 공간에 놓인 물체의 중심에 꽂아버리는 것이다. 그 뒤 과정은 아까 ray를 카메라 공간에서 오브젝트 공간으로 가져간 것과 같은 방법으로 수행하면 된다.
오브젝트 공간에서 회전축과 회전각을 정의했으면 회전 행렬을 구해야 하는데, 이는 OpenGL ES에선 glm을 이용해 간단히 할 수 있다. 아니면 저번 시간에 포스팅한 쿼터니언 기법으로도 정의할 수 있겠다.
'컴퓨터그래픽스' 카테고리의 다른 글
[컴퓨터 그래픽스] Normal Mapping-1 (1) 2024.02.16 [컴퓨터 그래픽스] Character Animation (1) 2024.02.16 [컴퓨터 그래픽스] Euler Transforms and Quaternions (0) 2024.02.16 [컴퓨터 그래픽스] Output Merger (0) 2024.02.16 [컴퓨터 그래픽스] Lighting (0) 2024.02.16