강체 물리
고친 사람 github-actions[bot]
강체 물리는 단단한 물체가 어떻게 움직이고 돌고 튕기는지 계산합니다. 물체의 모양은 늘 그대로라고 칩니다. 그래서 물체를 한 덩어리로 옮깁니다. 게임 속 상자가 굴러떨어지고 공이 바닥에서 튀어 오르는 장면이 이 계산에서 나옵니다. 게임의 물리 엔진이 맡는 계산 가운데 가장 기본이 되는 부분입니다.
쉽고 빠른 이해
무슨 일을 하나 — 단단한 물체의 움직임을 짧은 시간 간격마다 계산합니다. 책상 위 책의 모서리를 밀면 책이 밀려 나가는 동시에 빙글 돕니다. 이 움직임을 사람이 한 장면씩 짜 두지 않아도 계산이 만들어 냅니다.
왜 모양이 안 변한다고 치나 — 찌그러지는 것까지 계산하려면 물체 겉면의 수많은 점을 하나하나 따라가야 합니다. 모양이 안 변한다고 치면 물체 하나를 위치와 방향과 빠르기 몇 개만으로 나타낼 수 있습니다. 그만큼 계산이 줄어듭니다.
어떻게 도나
- 물체에 걸린 힘으로 움직이는 빠르기와 도는 빠르기를 바꿉니다
- 바뀐 빠르기만큼 물체를 옮기고 돌립니다
- 부딪힌 물체는 그 순간 빠르기를 단번에 바꿔 튕겨 냅니다
대가 — 찌그러짐이나 출렁임은 나타낼 수 없습니다. 고무공이나 옷자락은 다른 계산이 맡습니다. 쌓아 둔 물체가 조금씩 떨리기도 합니다. 맞닿은 물체끼리 서로 밀어내는 계산을 다 맞추지 못한 채 다음 간격으로 넘어가기 때문입니다.
상세
이 절은 강체 물리가 물체 하나를 어떤 값으로 나타내는지부터 봅니다. 그다음 힘이 그 값을 어떻게 바꾸는지 따라갑니다. 예로는 경첩에 달린 문을 씁니다.
뒤에서는 부딪힘과 쌓임을 어떻게 계산하는지 봅니다. 끝에서는 강체로 다루면 안 되는 물체를 짚습니다.
볼링공을 굴리면 공 겉면의 어느 점을 보든 공 전체와 함께 움직입니다. 물풍선을 던지면 다릅니다. 한쪽이 눌리면 다른 쪽이 출렁입니다. 점마다 따로 움직입니다.
강체 물리는 물체를 볼링공처럼 다룹니다. 어떤 힘을 받아도 찌그러지지 않는 한 덩어리로 봅니다. 그 덩어리가 어디로 가고 어느 쪽으로 도는지만 계산합니다.
강체라는 가정
강체(rigid body)는 힘을 받아도 물체 안의 두 점 사이 거리가 변하지 않는다고 치는 물체입니다. 벽돌 양 끝에 점을 하나씩 찍어 둔다고 해 봅니다. 벽돌을 던지든 떨어뜨리든 두 점 사이 거리는 늘 같습니다.
현실에 완전한 강체는 없습니다. 쇠공도 바닥에 부딪히는 순간 아주 조금 눌립니다. 눌리는 정도가 눈에 띄지 않을 만큼 작아서 무시해도 움직임은 거의 같습니다.
이 가정은 계산을 크게 줄입니다. 찌그러지는 물체는 겉면의 점 수천 개가 저마다 어디로 가는지 따라가야 합니다. 강체는 모든 점이 서로 묶여 있습니다. 물체 하나의 위치와 방향만 알면 모든 점의 위치가 정해집니다.
강체 하나를 나타내는 네 값
강체 물리는 물체마다 값 넷을 들고 다닙니다. 둘은 물체가 지금 어디에 어떻게 놓였는지를 나타냅니다. 나머지 둘은 그 둘이 얼마나 빨리 바뀌는지를 나타냅니다.
| 값 | 무엇을 나타내나 | 예 |
|---|---|---|
| 위치 | 물체가 어디에 있나 | 바닥에서 2 미터 위 |
| 방향 | 물체가 어느 쪽으로 돌아가 있나 | 시계 방향으로 30 도 |
| 선속도 | 어느 쪽으로 얼마나 빨리 움직이나 | 오른쪽으로 초속 3 미터 |
| 각속도 | 어느 축으로 얼마나 빨리 도나 | 1 초에 반 바퀴 |
위치는 보통 물체의 질량 중심을 가리킵니다. 질량 중심은 물체의 무게가 한 점에 모여 있다고 볼 수 있는 점입니다. 고르게 만든 막대라면 한가운데입니다. 이 점을 기준으로 삼는 까닭은 아래 「밀리는 운동과 도는 운동」에서 나옵니다.
평면 게임에서 방향은 각도 하나면 됩니다. 3차원에서는 물체가 세 축으로 돌 수 있어서 값이 더 필요합니다.
가장 쉬운 방법은 각도 셋을 쓰는 것입니다. 물체를 정해진 순서로 축마다 차례로 돌린다고 칩니다. 먼저 세로축으로 돌려 좌우를 바라보고, 다음에 가로축으로 돌려 고개를 듭니다. 마지막으로 앞뒤 축으로 돌려 옆으로 기울입니다. 이 방식에는 약점이 있습니다.
둘째 단계에서 고개를 90 도 들어 곧장 위를 보면, 앞뒤 축도 위를 가리킵니다. 그러면 첫째 축과 셋째 축이 같은 축이 됩니다. 둘 중 어느 각도를 바꿔도 같은 쪽으로만 돕니다.
축 하나를 잃은 셈이라 어떤 방향으로는 조금도 돌릴 수 없습니다. 이 현상을 짐벌 락이라고 합니다.
쿼터니언은 이 문제를 피하는 방법입니다. 쿼터니언은 수 넷으로 회전 하나를 나타냅니다. 축을 차례로 돌리지 않고 축 하나와 그 축으로 돈 양을 한꺼번에 담습니다. 그래서 축이 겹칠 일이 없습니다. 3차원 물리 엔진은 방향을 흔히 쿼터니언으로 담습니다.
밀리는 운동과 도는 운동
강체의 움직임은 둘로 나눠 봅니다. 하나는 질량 중심이 옮겨 가는 운동입니다. 다른 하나는 질량 중심을 축으로 도는 운동입니다. 두 운동은 꼴이 같은 규칙을 따릅니다.
밀리는 운동은 뉴턴 운동 법칙의 둘째 법칙을 따릅니다. 물체에 걸린 힘을 질량으로 나누면 가속도가 나옵니다. 가속도는 속도가 1 초 동안 얼마나 바뀌는지를 나타내는 값입니다.
도는 운동에서 힘 노릇을 하는 값은 토크입니다. 토크는 물체를 돌리려는 힘의 세기입니다. 힘의 크기에 회전축에서 힘을 준 점까지의 거리를 곱해서 구합니다.
문손잡이가 경첩 반대쪽 끝에 달린 까닭이 이것입니다. 같은 힘으로 밀어도 경첩에서 멀리 밀수록 토크가 커집니다. 토크가 클수록 문이 쉽게 돕니다.
도는 운동에서 질량 노릇을 하는 값은 관성 모멘트입니다. 관성 모멘트는 물체를 돌리기가 얼마나 어려운지를 나타냅니다. 질량이 같아도 무게가 축에서 멀리 퍼져 있을수록 커집니다. 같은 쇠막대라도 한가운데를 잡고 돌릴 때보다 한쪽 끝을 잡고 돌릴 때 힘이 더 듭니다.
3차원 물체는 축마다 돌리기 어려운 정도가 다릅니다. 연필은 길이 방향 축으로는 손가락으로 쉽게 굴러갑니다. 그 축에 수직으로 돌리려면 힘이 더 듭니다.
그래서 3차원에서는 관성 모멘트를 값 하나로 담지 않습니다. 축마다 돌리기 어려운 정도를 묶은 행렬 하나로 담습니다. 이 행렬을 관성 텐서라고 부릅니다.
각속도가 1 초 동안 바뀌는 양은 각가속도라고 부릅니다. 이제 두 운동의 값을 나란히 놓아 봅니다.
| 밀리는 운동 | 도는 운동 |
|---|---|
| 위치 | 방향 |
| 선속도 | 각속도 |
| 힘 | 토크 |
| 질량 | 관성 모멘트 |
| 가속도 = 힘 ÷ 질량 | 각가속도 = 토크 ÷ 관성 모멘트 |
표의 두 칸은 낱말만 바꾼 꼴입니다. 밀리는 운동의 식을 알면 도는 운동의 식도 같은 모양으로 읽힙니다.
힘 하나가 두 운동을 함께 일으키기도 합니다. 책상 위 책의 한가운데를 밀면 책은 돌지 않고 밀려 나갑니다. 모서리를 밀면 밀려 나가는 동시에 빙글 돕니다.
힘이 질량 중심을 곧장 향하면 물체는 밀리기만 합니다. 질량 중심을 비켜 가면 비켜 간 거리만큼 토크가 생겨 물체가 돕니다. 위치를 질량 중심으로 잡는 까닭이 이것입니다. 질량 중심을 기준으로 삼아야 밀리는 몫과 도는 몫을 따로 계산할 수 있습니다.
한 스텝 안에서 값이 바뀌는 순서
물리 엔진은 시간을 아주 짧은 간격으로 잘라 한 칸씩 나아갑니다. 한 칸을 계산하는 일을 물리 스텝이라고 부릅니다. 강체 물리는 스텝마다 네 값을 아래 순서로 새로 씁니다.
flowchart TD
F["물체에 걸린 힘"]
subgraph M["밀리는 운동"]
A1["가속도를 구한다"] --> V1["선속도를 바꾼다"]
V1 --> P1["위치를 옮긴다"]
end
subgraph R["도는 운동"]
A2["각가속도를 구한다"] --> V2["각속도를 바꾼다"]
V2 --> P2["방향을 돌린다"]
end
F -->|"질량으로 나눈다"| A1
F -->|"토크로 바꿔 관성 모멘트로 나눈다"| A2
두 갈래 모두 가속도, 속도, 위치 순서로 내려갑니다. 도는 쪽은 힘을 먼저 토크로 바꾼다는 점만 다릅니다.
경첩에 달린 문을 밀 때 첫 스텝을 따라갑니다. 문은 경첩을 축으로만 돌 수 있으니 도는 운동만 보면 됩니다.
각도는 라디안이라는 단위로 잽니다. 한 바퀴가 약 6.28 라디안입니다.
F = 10.0 # 미는 힘, 뉴턴
r = 0.8 # 경첩에서 손까지, m
I = 4.0 # 관성 모멘트, kg·m²
dt = 1 / 50 # 스텝 간격, 초
w = 0.0 # 처음 각속도
th = 0.0 # 처음 각도
tau = F * r # 8.0
al = tau / I # 2.0
w = w + al * dt # 0.04
th = th + w * dt # 0.0008
코드의 tau 는 토크입니다. al 은 각가속도입니다. 코드 끝의 네 줄이 앞 그림의 「도는 운동」 칸을 차례로 밟습니다.
한 스텝 뒤 문은 1 초에 0.04 라디안 빠르기로 돌기 시작했습니다. 각도는 아직 0.0008 라디안만 돌았습니다. 마지막 두 줄을 되풀이하면 각속도가 스텝마다 0.04 씩 커집니다.
이번에는 손을 경첩 쪽으로 옮겨 0.2 미터 거리에서 같은 힘으로 밀어 봅니다. 토크는 2.0 으로 줄어듭니다. 각가속도도 4 분의 1 인 0.5 가 됩니다. 문손잡이를 경첩에서 멀리 다는 까닭이 숫자로 드러납니다.
속도를 먼저 바꾸고 바뀐 속도로 위치를 옮기는 이 순서에는 이름이 있습니다. 반암시적 오일러 방법입니다.
위치를 먼저 옮기고 속도를 나중에 바꾸는 순서도 있습니다. 이 순서는 바뀌기 전의 낡은 속도로 위치를 옮깁니다. 그래서 스텝마다 에너지가 조금씩 불어나는 오차가 쌓입니다. 물체가 점점 빨라집니다. 물리 엔진은 대개 속도를 먼저 바꿉니다.
부딪힘을 계산하는 법
이 소절은 강체끼리 부딪힌 순간을 어떻게 계산하는지 봅니다. 상자 하나가 모서리부터 바닥에 떨어지는 장면으로 따라갑니다.
부딪힘은 아주 짧은 순간에 끝납니다. 그 순간 두 물체는 아주 큰 힘으로 서로를 밉니다. 이 순간은 스텝 간격보다 훨씬 짧습니다. 그래서 그 힘을 스텝마다 나눠 계산할 수가 없습니다.
강체 물리는 힘 대신 임펄스를 씁니다. 임펄스는 짧은 순간에 준 힘을 모두 더한 양입니다. 임펄스를 받으면 물체의 속도가 단번에 바뀝니다. 그래서 부딪힌 스텝에서 속도를 바로 고쳐 씁니다.
속도가 얼마나 바뀌는지는 운동량으로 셉니다. 운동량은 질량에 속도를 곱한 값입니다. 물체는 받은 임펄스만큼 운동량이 바뀝니다. 같은 임펄스를 받아도 질량이 큰 물체일수록 속도가 조금 바뀝니다.
임펄스는 부딪힌 면에 수직인 방향으로 줍니다. 면에 수직인 방향을 법선 방향이라고 합니다. 평평한 바닥이라면 법선은 곧장 위를 가리킵니다.
반발 계수는 되튀는 빠르기가 부딪히기 전 빠르기의 몇 배인지 정하는 0 에서 1 사이 값입니다. 움직이지 않는 벽에 초속 4 미터로 부딪힌 공은 반발 계수가 0.5 면 초속 2 미터로 튕겨 나옵니다.
임펄스의 크기는 이 비율이 맞도록 정해집니다. 그래서 반발 계수가 같아도 무겁고 빨리 날아온 공일수록 큰 임펄스를 받습니다. 반발 계수가 0 이면 공을 멈춰 세울 만큼만 줍니다. 공은 튕기지 않고 벽에 붙습니다.
이제 상자를 떨어뜨려 봅니다. 상자가 모서리부터 떨어지면 바닥이 그 모서리를 위로 밀어 올립니다. 모서리는 질량 중심에서 비켜나 있습니다. 그래서 임펄스가 상자를 튀어 오르게 하는 동시에 돌립니다. 상자가 모서리로 튀었다가 한 면으로 넘어지는 까닭입니다.
어느 물체끼리 부딪혔는지 찾는 일은 충돌 감지가 맡습니다. 충돌 감지는 두 물체가 닿은 점과 그 점의 법선을 찾아 넘깁니다. 두 물체가 닿은 점을 접촉점이라고 합니다.
강체 물리는 넘겨받은 접촉점과 법선으로 임펄스를 계산합니다. 임펄스로 속도를 고치는 이 단계를 충돌 응답이라고 부릅니다.
쌓인 물체와 이어진 물체
부딪혔다 떨어지는 물체만 있는 것은 아닙니다. 바닥에 놓인 상자는 계속 바닥에 닿아 있습니다. 문은 경첩에서 떨어지지 않습니다.
이렇게 물체가 늘 지켜야 하는 조건을 구속 조건이라고 합니다. 「바닥을 뚫고 들어가지 않는다」와 「경첩 점에서 떨어지지 않는다」가 그 예입니다.
물리 엔진은 스텝마다 구속 조건이 깨진 곳을 찾습니다. 그리고 임펄스를 줘서 바로잡습니다. 상자 다섯 개가 쌓여 있으면 한 상자를 바로잡는 임펄스가 위아래 상자의 조건을 다시 흔듭니다. 그래서 모든 조건을 여러 바퀴 돌며 조금씩 맞춰 갑니다.
바퀴 수를 줄이면 계산이 줄어듭니다. 대신 조건이 덜 맞춰진 채 스텝이 끝납니다. 남은 어긋남은 쌓인 상자를 조금씩 떨게 합니다. 바퀴 수를 늘리면 떨림이 줄어듭니다. 대신 계산이 늘어납니다.
두 물체를 구속 조건으로 묶어 두는 연결은 조인트라고 부릅니다. 문과 문틀을 잇는 경첩이 조인트의 한 예입니다.
강체 여럿을 조인트로 이어 사람 몸 모양을 만들 수도 있습니다. 힘없이 쓰러지는 캐릭터를 이렇게 만듭니다. 이런 캐릭터를 래그돌이라고 부릅니다.
강체 가정이 맞지 않는 물체
강체 물리는 모양이 안 변한다는 가정 위에 서 있습니다. 그래서 모양이 바뀌는 것 자체가 중요한 물체에는 맞지 않습니다. 아래 표는 그런 물체와 대신 쓰는 계산입니다.
| 물체 | 강체로 못 나타내는 것 | 대신 쓰는 계산 |
|---|---|---|
| 고무공 · 젤리 | 눌렸다 돌아오는 모양 | 연체 물리 |
| 옷자락 · 깃발 | 접히고 펄럭이는 면 | 천 시뮬레이션 |
| 물 · 연기 | 흐르고 퍼지는 물질 | 유체 시뮬레이션 |
| 다리 · 건물 기둥 | 힘을 받아 미세하게 휘는 정도 | 유한 요소법 |
표의 계산은 모두 물체를 수많은 점이나 조각으로 쪼개 따로 따라갑니다. 강체가 위치와 방향 하나로 끝나는 것과 달리 계산이 훨씬 많이 듭니다. 그래서 게임은 화면 속 물체 대부분을 강체로 둡니다. 모양이 바뀌는 게 눈에 띄는 몇 가지에만 위 계산을 붙입니다.
쓰이는 분야
강체 물리는 물체끼리 부딪히고 쌓이고 무너지는 장면이 많은 게임에서 씁니다. 상자 서른 개가 무너지는 모양은 매번 달라서 사람이 한 장면씩 짜 둘 수 없습니다. 게임을 만드는 도구 묶음인 게임 엔진은 대개 강체 물리를 계산하는 물리 엔진을 품고 있습니다.
게임 밖에서는 로봇 팔이나 차량을 만들기 전에 컴퓨터 안에서 먼저 움직여 봅니다. 이런 시뮬레이션은 게임과 달리 빠르기보다 정밀함을 먼저 봅니다. 스텝 간격을 더 잘게 자르고 구속 조건을 더 여러 바퀴 맞춥니다.
플레이어가 조종하는 캐릭터는 강체 물리에 맡기지 않는 경우가 많습니다. 힘으로만 움직이면 서고 도는 반응이 둔해지기 때문입니다. 이런 물체는 코드가 위치를 직접 정합니다. 힘을 받지 않고 코드가 옮기는 물체를 키네마틱 물체라고 부릅니다.
관련 항목
강체 하나를 나타내는 물리량
강체 · 질량 · 질량 중심 · 관성 모멘트 · 관성 텐서 · 선속도 · 각속도 · 쿼터니언 · 짐벌 락 · 라디안
강체의 운동을 바꾸는 힘과 법칙
뉴턴 운동 법칙 · 가속도 · 각가속도 · 토크 · 운동량 · 각운동량 · 임펄스
강체 물리가 한 스텝 안에서 거치는 처리 단계
물리 스텝 · 적분 · 오일러 방법 · 반암시적 오일러 방법 · 충돌 · 충돌 감지 · 충돌 응답 · 법선 · 반발 계수 · 마찰 계수 · 고정 타임스텝
강체를 이어 붙이는 연결 방식
구속 조건 · 조인트 · 힌지 조인트 · 볼 조인트 · 래그돌
강체 가정을 버리는 다른 시뮬레이션
연체 물리 · 천 시뮬레이션 · 유체 시뮬레이션 · 유한 요소법
물리 엔진 안에서 강체와 함께 놓이는 물체 종류
키네마틱 바디 · 정적 바디 · 콜라이더 · 트리거 콜라이더
강체 계산에서 자주 나는 오류와 그 대책
터널링 · 연속 충돌 감지 · 슬리핑 · 부동소수점 오차 · 결정론적 시뮬레이션
강체 물리를 품는 상위 분류
물리 엔진 · 게임 엔진 · 게임 개발 · 시뮬레이션 · 로보틱스
강체 물리를 구현한 라이브러리
Box2D · PhysX · Havok · Bullet Physics · Jolt Physics
다른 이름: rigid body physics · rigid body dynamics · rigid body simulation · 강체 동역학 · 강체 시뮬레이션