ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • GGP 10. Screen-space Object Manipulation
    게임그래픽프로그래밍 2024. 6. 8. 00:55

    Object Picking

    우리가 스크린에서 클릭을 하였을 때, 어떤 object를 클릭한건지를 알아내는 과정이 필요하다. 우리가 클릭한 스크린 상의 좌표는 (xs,ys)이고, 이 좌표가 ray의 시작점 좌표가 된다 (xs, ys,0). ray는 z축 방향으로 쏘며 이 direction vector은 (0,0,1)방향이다.

     

     

    우리가 찾아내야 될 것은, ray와 부딪힌 object이다. 그러나, screen-space의 정보로는 어떤 object의 픽셀인지를 알 수 없다. 따라서, screen-space에서 object-space로 전환하여 object spaces에서 intersection test를 수행해야 한다.

     

    Camera-space Ray

    camera-space의 ray의 시작점은 (xc, yc, n)이다. 이때 n은 near plane이다.  direction vector은 여전히 (0,0,1)이므로, 아래 그림 상에서 빨간 점선으로 나타내진 벡터는 (0,0,1)방향으로 나아가는 screen space에서의 ray vector을 의미한다.

    1. 우리는 camera-space에서 projection matrix를 곱하여 clip space로 전환하였다.

    이전 포스팅에서 다루었듯이, (xc,yc,n,1)에 projection matrix를 곱하면 clip space로 전환되고, 좌표를 -1~1 사이로 정규화하면 NDC에서는 아래와 같은 좌표를 갖게 된다.

    2024.05.18 - [게임그래픽프로그래밍] - GGP 4. Input Assembler & Vertex Processing(2)

     

    GGP 4. Input Assembler & Vertex Processing(2)

    지난 포스팅에서 Vertex shader에는 4가지 world와 3가지 transform이 있는 것을 배웠다. 이번 포스팅에서는 camera space에서 clip space로 가는 projection transform에 대해 다루겠다. View Frustum카메라는 모든 물체

    chaengdiary.tistory.com

    projection matrix(좌), projection transform을 거친 후의 NDC(우)

     

     


    2. viewport matrix를 곱해 screen space로 전환된다. 

    viewport matrix를 곱해 얻은 좌표
    전체적인 과정(camera space -> clip space -> screen space)

     

    우리는 screen-space에서 (xs,ys)라는 점이 클릭된 것을 안다. 우리가 얻어야할 것은, camera space에서 ray의 시작점인 xc,yc인데 아래 방정식을 풀면 xc와 yc를 xs, ys로 표현할 수 있다. 

     

     

    direction vector은 원점에서 start point(xc,yc)를 빼서 구할 수 있다. 이 벡터가 앞 그림의 빨간 점선 벡터이다.

     

     

    World-space Ray

    camera-space ray를 object-space ray로 옮겨야 한다. world space -> camera space로 갈때 view transform을 해주었으므로, 거꾸로 camera space -> world space로 갈때는 view transform의 역연산을 해주어야 한다.

    즉, Mview = TR(translation -> rotation)이었는데, Mview^ (-1)는 (TR)^(-1) = R^(-1)T^(-1)이다. T는  -EYE로 이동되므로, T^(-1)는 +EYE이다. 회전의 역행렬은 전치행렬이다

     

     

     

    정리하자면 다음 그림과 같다.

    camera space에 Mview의 역행렬을 곱하여  world space로 전환하였다. 이때, picking ray는 카메라가 바라 보는 방향이며, 이 picking ray와 object가 교차하면 picking이 되는 것이다. 그러기 위해서는 object space까지 ray를 보내야 된다. 위 그림에서는 world space에서 구와 말이 정의 되었는데, 이 각각의 object는 자신만의 object space가 존재하고, 독립된 world matrix를 각각 가진다.

     

    Object-space Ray

    각 object들은 자신만의 world transforms를 가진다. 따라서 각 object마다 따로 정의된 world matrix의 역행렬을 곱하여 object space로 보낸다. 각 object 별로 object space에 존재하는 picking ray를 만들 것이다. 아래 그림을 보면 구와 말에 오는 picking ray의 위치가 각각 다른 것을 확인할 수 있다.

    Intersection per object

    우리는 ray가 polygon mesh로 나타내진 object를 통과하는지 알아보기 위해서는 각 삼각형 마다 모두 ray-triangle intersection test를 수행해야한다. 근데 이건 매우 비용이 많이든다. 우리는 정확도는 조금 희생하지만 더 빠른 방법을 선호하는데, 이 방법을 bounding volume(BV)라고 한다.

     

    Bounding Volumes

    polygon mesh를 감싸는 bounding volumes은 AABB(axis-aligned bounding box) 와 bounding sphere의 두 종류가 있다. AABB는 회전 없이 (x,y,z)축과 평행하기만 한 박스모양이라 연산이 간단하고, bounding sphere은 구의 중심으로부터의 거리만 신경쓰기에 연산이 간단하다. 정확한 연산이 필요할 때는 bounding volumes을 여러 개 만들기도 한다.

     

     

    Ray-BV Intersection

    ray와 BV가 교차하는지 확인하는 ray-sphere intersection test를 하기위해 우리는 ray를 다음과 같이 표현한다.

    우리는 구의 방정식에 x(t),y (t),z(t)를 대입한 후, t에 대한 이차방정식의 판별식을 이용해 교차했는지 확인할 것이다.

     ray와 교차하지 않는 polygon mesh는 버린다. 만약 더 정교한 결과를 원한다면, ray-triangle intersection test나 multiple bounding volume test를 하면 된다.

     

    Ray-Triangle Intersection

     

    picking ray가 삼각형 내부에 부딪힌다면 (p), p에 의해 삼각형은 세 삼각형으로 쪼개진다. u를 전체 삼각형 넓이에 대한 작은 삼각형(p,b,c) 넓이의 비율이라고 보면, u가 클수록 p가 a에 더 가까워진다는 것을 의미한다. 이는 p에대한 a의 가중치를 나타낸다. 마찬가지로 b,c에 대한 가중치도 v,w로 구할 수 있다. u+v+w = 1이다.

     

    ray를 s+td로 나타내었을때, p = s+ td이면서, ua+vb+wc이다.

    이 방정식을 풀면, 다음과 같이 t,u,v를 Cramer's rule로 풀 수 있게 된다.

     

    Cramer's rule은 다음과 같다.

     

     

    한계: p가 항상 삼각형 내부에 있어야 된다. (u >=0, v>=0, u+v<=1)

    하나의 ray에 여러 개의 교차점이 발생한다면, 가장 작은 양수값을 갖는 t를 선택해야 한다.

     

    Rotating an object

     

    우리가 스크린에서 손가락을 슬라이딩 하면 {p1,p2,... pn} 3D 회전이 계산되고, 오브젝트에 적용 된다. screen에서의 벡터 변화로 object space의 벡터 변화를 나타낼 수 있어야 한다.

     

    Arcball

    arcball은 가상의 ball로, screen뒤에 위치하여 object가 회전하도록 하는 것이다. 스크린에서 손가락으로 슬라이딩 하는 것은 arcball을 회전시킨다. 그리고 같은 회전이 object에도 적용된다. 더 효율적인 실행을 위해 , w x h크기의 2d screen을 2x2 네모에 normalized한다. 그리고 스크린에서의 손가락 위치인 (x,y)는 pi, pi+1로 normalized되었는데, 이는 각각 qi, qi+1로 네모에서 바뀐다.

     

     

    그 다음, q는 z를 따라 arcball의 표면으로 정사영된다. v를 구의 중심과 정사영된 점을 이은 벡터라고 했을 때, vx = qx, vy= qy, vz = ( 1 - vx^2 - vy^2)^0.5 (arcball은 반지름이 1인 구)로 나타낼 수 있다. 만약, projection이 arcball의 밖으로 나갔다면, 크기를 1로 normalized 해준다. 같은 방법으로 vi+1도 구한다.

    vi, vi+1이 주어졌으므로 우리는 rotation axis와 angle을 구할 수 있다. rotation axis는 vi와 vi+1을 외적하여 구할 수 있고, rotation angle은 두 벡터를 내적하여 얻을 수 있다.

     

    rotation은 world transform이 일어나기 전에 일어나야 하므로, 회전 축은 object space(여기서 회전 일어남)에서 정의되어야 한다. arcball space에서 rotation axis를 계산하였는데, arcball space라는건 GPU Pipeline에 존재하지 않는다. 따라서, camera space 대신 arcball space를 넣어 회전을 계산한다. 먼저 회전을 한 후에, world transform, view transform등을 정의해야 한다. 회전 축은, camera space에서 object를 뚫고 지나가는데, object space에서 그 구성이 잘 보존된다.

    '게임그래픽프로그래밍' 카테고리의 다른 글

    GGP 12. Character Animation  (0) 2024.06.10
    GGP 11. Normal Mapping and Tessellation  (0) 2024.06.09
    GGP 9. Euler transforms and quaternions  (0) 2024.06.07
    GGP 8. Output-Merging  (0) 2024.06.07
    GGP 7. Lighting  (0) 2024.06.06
Designed by Tistory.