-
[Unreal] Unreal Engine IK solver - IK는 어떤 원리로 동작할까?쾌락없는 책임 (공부)/Unreal 2023. 3. 20. 13:23반응형
개요
엔진에서 IK 관련한 기능들을 많이 사용하게 됩니다. 발을 땅에 자연스럽게 옮긴다던가, 손 한쪽을 무기를 받치게 수정해 준다던가. 이런 기능들을 사용하면서 대충 본을 이 위치로 옮겨준다는 생각만 했지 원리에 대해서는 크게 생각해 본 적이 없습니다. 그래서 이번에 FK, IK의 차이점을 알아보고 IK solver들은 어떤 것들이 있는지 알아볼 예정입니다.
IK와 FK
FK가 IK에 비해서 조금 더 쉬운 느낌입니다. 간단하게 본이 있으면 본에 회전을 적용해 움직이는 방식입니다. 팔을 예시로 들면 '팔 관절을 움직여 팔을 움직인다'라는 조금 이두운동에 가까운 느낌을 줍니다.
단순히 회전을 적용하면 되는 것이기에 큰 비용이 발생하지는 않으나 직관적이지 못한 문제가 발생하게 됩니다. 예를 들어 '컵을 주워야지' 라고 하면 손을 컵에 가져다 대는 상상을 하지 '관절을 이렇게 움직이면 손이 팔에 닿을 거야' 같은 상상은 안 하니깐요. 그래서 등장하게 된 것이 IK입니다.
IK는 FK의 반대되는 개념으로 '타겟을 선정하고 이후 본들을 그 위치에 오도록 회전'하는 개념입니다. 원래 로보틱스에 많이 사용되던 개념이라고 합니다. 위의 팔 예시에서 '손을 움직여 컵을 집는다' 부분이 IK에 해당하는 개념이 되겠죠.
일단 이렇게 타겟을 위치로 옮긴다는 점에서 게임의 여러 기능과 잘 맞아떨어지는 기능입니다. 예를 들어 오른손에 총을 장착하고 왼손을 '손잡이'로 이동시키겠다라고 하면 손잡이를 타겟으로 잡는 IK가 더 직관적인 해결법이 됩니다.
IK Solvers
다만 이런 IK 기능들은 단순 관절을 움직이는게 아닌 '타겟을 잡은 뒤 이에 맞춰 관절을 움직이는 형태'라서 더 복잡한 알고리즘이 필요하게 됩니다.
[Two Bone IK]
일단 인터넷에 여러 Ik Solver 들을 찾아보다가 발견하게 된 알고리즘인데 현재 언리얼 엔진 5 에서 사용하고 있는지는 아직 발견하지 못했습니다. 아래 2개의 경우 저도 써봤거나 블루프린트 노드로 발견을 했었는데 이 알고리즘은 사용하고 있는지 잘 모르겠네요.
이 알고리즘의 순서는 아래와 같습니다.
- 본이 2개만 있는 형태입니다. (팔에서 상완과 전완만 있는 모습)
- 여기서 target 이 정해지게 되면 본의 각도는 코사인 법칙으로 구합니다.
- 코사인 법칙으로 나온 2개의 각도 중 하나를 선택합니다.
이 방법의 경우 코사인 법칙을 사용하면 위 그림처럼 2가지 해가 나오게 됩니다. 이를 잘 해결하기 위해서 어느 정도의 제약을 추가하게되는데 관절이 대부분 한 방향으로 꺾이기 때문에 이를 바탕으로 각도의 제한을 걸게 됩니다.
다만 이 알고리즘의 경우 본을 2개만 판단하는 거라 자연스러운 움직임이 나오지는 않는다는 단점이 있습니다. 2D에서 사용은 적절해 보이나 3D나 복잡한 본 구조에서는 이 방법을 직접 사용할 수는 없기에 아래 알고리즘들을 사용하게 됩니다.
[CCDIK - Cyclic Coordinate Descent Inverse Kinematics]
CCDIK 알고리즘부터 여러 본을 순회하면서 검사하기 때문에 비용이 점점 비싸지게 됩니다.
이 알고리즘의 순서는 아래와 같습니다.
- 기본 관절의 위치는 고정 합니다.
- End 지점부터 해서 각 Joint를 회전시켜 최대한 타겟에 맞춥니다
- 원하는 결과가 나올 때까지 이를 반복합니다.
아래 나올 FABRIK 보다 간단한 알고리즘이고 중간중간 관절의 각도를 계산하는 건 두 벡터의 내적으로 처리한다고 합니다. 비용이 적은 장점이 있는 알고리즘이지만 Target이 이상하면 이에 따라 이상한 결과가 도출될 수도 있다 합니다.
[FABRIK - Forward And Backward Reaching Inverse Kinematics]
위 CCDIK 처럼 반복적으로 진행되는 알고리즘입니다. 이 알고리즘의 순서는 아래와 같습니다.
- 일단 Target에 맞게 본의 End(P4')를 이동해 줍니다. (Forward 작업 시작)
- 이동된 위치에 맞게 따라오는 본도 이동해 줍니다. 단, 이때 기존 Joint 간 거리는 유지해 줍니다.
- 위 2 과정을 마지막 본(P1 -> P1')까지 반복합니다.
- 이후 P1'를 다시 원래 위치로 옮기게 됩니다. (Backward 작업 시작)
- 이후 이를 역순으로 P4' (최종 P4'')까지 진행합니다.
참고자료
- FABRIK 기초 논문으로 출처 되었는데 사실 읽지는 못하고 이에 대한 해석을 참고했습니다.
http://www.andreasaristidou.com/publications/papers/FABRIK.pdf
- 논문 해석에 도움이 된 일본 글입니다.
- Unreal Engine의 CCDIK, FABRIK 블루프린트 노드 설명입니다.
반응형'쾌락없는 책임 (공부) > Unreal' 카테고리의 다른 글
[Unreal] 언리얼 ListView 간단하게 알아보기 (0) 2023.03.23 [Unreal] Unreal StaticMeshComponent0 has to be ‘Movable’ if you’d like to move 경고 (0) 2023.03.21 [Unreal] Additive Animation - 애디티브 애니메이션 (1) 2023.03.13 [Unreal] 언리얼 블루프린트 vs C++, 왜 프로그래머는 C++을 써야 하는가? (0) 2023.03.10 [Unreal] 언리얼 인터페이스 이야기 - Unreal C++ Interface (0) 2022.11.28