LabHub
배우기 러닝패스 코스

물리 엔진의 뼈대 · 제약과 안정성 · 이론

상자가 가라앉지 않게

LabHub 에서 이어서 보기

한 줄 요약

속도만 고쳐서는 이미 파고든 겹침이 사라지지 않습니다. 위치를 따로 밀어 주되, 너무 세게 밀면 떨리므로 여유(슬롭)를 두고 조금씩 밀어야 합니다. 접촉이 여럿이면 같은 걸음 안에서 여러 번 반복해 풉니다.

왜 이게 필요했나

앞 모듈의 충격량은 속도를 고칩니다. 바닥에 닿은 상자의 아래 방향 속도를 0 으로 만들면 더 내려가지는 않습니다. 그런데 그 상자는 이미 조금 파고든 상태입니다. 겹침을 알아채는 시점이 이미 겹친 뒤이기 때문입니다.

속도가 0 이 되었으니 상자는 그 파고든 자리에 그대로 머뭅니다. 다음 걸음에서 중력이 다시 속도를 주고, 위치가 조금 더 내려가고, 다시 0 이 됩니다. 조금씩 가라앉습니다. 상자를 여러 개 쌓으면 아래쪽이 눌려 서로 파고든 채로 굳습니다.

어떻게 동작하나

위치 보정은 겹친 만큼을 역질량 비율로 나눠 양쪽을 밀어내는 것입니다.

보정량 = max(깊이 - slop, 0) / (inv_m1 + inv_m2) * percent물체1 을 -n 방향으로 보정량 * inv_m1 만큼물체2 을 +n 방향으로 보정량 * inv_m2 만큼

여기 두 개의 손잡이가 있습니다. percent 는 한 걸음에 몇 퍼센트를 되돌릴지입니다. 1.0 으로 두면 한 번에 다 밀어내는데, 그러면 물체가 튕겨 나가고 다음 걸음에 다시 부딪히는 진동이 생깁니다. 보통 0.2 에서 0.8 사이를 씁니다.

slop 은 무시할 겹침의 여유입니다. 보통 0.005 에서 0.01 정도를 두는데, 이게 없으면 겹침을 0 으로 만들려는 보정이 매 걸음 아주 작은 값으로 계속 일어나 물체가 미세하게 떨립니다. 겹침을 정확히 0 으로 만들려 하지 않고 아주 얇게 겹친 상태로 두는 것이 오히려 안정적입니다.

위치 보정은 속도를 건드리지 않는다는 점도 중요합니다. 위치만 옮기므로 에너지를 만들어 내지 않습니다. 속도까지 바꾸면 보정이 물체를 밀어 주는 힘이 되어 더미가 스스로 튀어 오릅니다.

반복 횟수는 접촉이 여럿일 때 필요합니다. 상자 세 개가 쌓여 있으면 접촉이 셋(바닥-1, 1-2, 2-3)인데, 이것들은 서로 얽혀 있습니다. 맨 위 상자를 밀면 가운데가 눌리고, 가운데를 고치면 아래가 눌립니다. 접촉을 하나씩 순서대로 풀면 나중에 푼 것이 앞서 푼 것을 망가뜨립니다.

정확한 해법은 모든 접촉을 하나의 연립방정식으로 푸는 것인데 비쌉니다. 그래서 엔진들은 같은 순회를 여러 번 반복합니다. 반복할수록 정답에 가까워지고, 반복을 멈추는 지점이 곧 정확도와 비용의 절충입니다. 이것을 순차 충격량(sequential impulse)이라고 하고, Erin Catto 가 Box2D 에서 정리한 뒤로 사실상 표준이 되었습니다. 상자 더미가 얼마나 단단해 보이는지가 이 반복 횟수에 거의 그대로 달려 있습니다.

위치 보정 말고 다른 길도 있습니다. 바움가르테 안정화는 겹침의 일부를 속도 목표값에 섞어 넣는 방법입니다. "상대 속도를 0 으로 만든다" 대신 "상대 속도를 beta * 깊이 / dt 로 만든다" 로 목표를 바꾸면, 속도 해법 안에서 겹침이 함께 밀려납니다. 구현이 간단해 널리 쓰였지만 에너지를 계에 넣어 주는 부작용이 있어서, 더미가 미세하게 들썩이는 원인이 되기도 합니다.

그래서 요즘 엔진은 분할 충격량(split impulse) 을 씁니다. 속도를 고치는 충격량과 위치를 고치는 충격량을 따로 두고, 위치용 충격량은 실제 속도에 반영하지 않는 것입니다. 겹침은 밀려나면서 에너지는 들어오지 않아 두 방식의 장점만 남습니다. 이 실습의 위치 보정은 그 아이디어를 가장 단순하게 줄인 형태입니다.

현장에서 만나는 모습

더미가 시간이 지나면서 서서히 낮아지는 현상은 반복 횟수가 모자란 것입니다. 아래쪽 접촉이 다 풀리기 전에 걸음이 끝나 매 걸음 조금씩 눌립니다. 반복을 늘리면 눈에 띄게 좋아지지만 비용도 그만큼 듭니다.

또 하나는 잠재우기(sleeping) 입니다. 더미가 안정되면 계산은 계속 도는데 결과는 거의 변하지 않습니다. 엔진은 속도가 문턱 아래로 일정 시간 유지되면 그 물체를 계산에서 빼고, 무언가 닿으면 깨웁니다. 상자 1,000개가 쌓인 장면이 실제로 돌아가는 이유가 이것입니다.

마지막으로 더미의 안정성을 무엇으로 재는가 를 정해 두면 좋습니다. 눈으로 보아 흔들리지 않는다는 말은 판정 기준이 되지 못합니다. 실습에서 쓰는 방법은 두 가지입니다. 하나는 접촉의 최대 관통 깊이가 슬롭 근처에 머무는가이고, 다른 하나는 연속한 두 프레임의 그림 차이가 0 으로 수렴하는가입니다. 뒤쪽은 사람이 보는 것과 같은 것을 재기 때문에 특히 쓸모가 있습니다 — 숫자가 조금씩 움직여도 화면에서 같은 픽셀이면 사람에게는 멈춘 것입니다.

그리고 이 층의 규칙 하나를 기억해 두십시오 — 정확함보다 흔들리지 않는 것이 먼저입니다. 겹침을 정확히 0 으로 만들려는 시도가 떨림을 만들고, 한 걸음에 다 되돌리려는 시도가 튐을 만듭니다. 조금 겹친 채로 조용히 서 있는 더미가, 정확히 맞닿았지만 미세하게 진동하는 더미보다 낫습니다.

다음 실습에서 할 것

위치 보정 함수를 만들고, 보정 없이 굴린 상자가 파고든 채로 굳는 것과 보정을 켰을 때 슬롭까지 되돌아오는 것을 숫자로 비교합니다. 그다음 상자 세 개에 반복 횟수를 1, 4, 10 으로 바꿔 가며 관통 깊이가 줄어드는 것을 확인하고, 마지막에는 상자 다섯 개가 떨어져 쌓여 안정되는 과정을 열두 장의 그림으로 남깁니다.