2015년 1월 4일 일요일

고교 수학 수준 컴퓨터 게임 물리 시뮬레이션

고등학교 수학 수준의 컴퓨터 게임 물리 시뮬레이션을 만드는 방법이다. 내 대가리가 대학 수준으로 설명할 수준이 안 되고, 옛날 블로그도 다 날려서 공식이 기억도 안 난다. 그래서 아이디어만 정리 해 본다.


1. 에너지 → 힘 → 가속도 → 속도 → 거리




에너지는 자동차 연료통의 크기라고 보면 되고, 힘은 자동차 엔진 크기라고 보면 된다. 큰 힘을 내려면 엔진이 크고 순간 에너지 공급 양이 많아야 한다. 에너지를 소모하면 힘이 나온다. 그런데 같은 힘이라도 무거운 차와 가벼운 차일 때 가속도가 다르다. 이 가속도가 속도의 변화로 이어지고, 속도가 거리 변화로 이어진다. 이를 물리 공식으로 나타내면 아래와 같다.

  • e = f * d (에너지 = 힘*거리)
  • f = m * a (힘 = 질량*가속도)
  • v = a * t (속도 = 가속도*시간)
  • d = v * t (거리 = 속도*시간)

컴퓨터 게임에선 Δt (1/30초 또는 1/60초 순간/찰나) 동안 상태가 일정하다고 가정하고 물리 시뮬레이션을 한다. 그럼 다음과 같은 식으로 계산을 할 수 있다.

  1. 힘 f = 임의로 정한다. 적당한 연료를 소모했다고 보자.
  2. 가속도 a = f/m
  3. 속도 변화 Δv = a*Δt
  4. 속도 수정 v.new = v.old + Δv
  5. 거리 변화 Δd = v.new*Δt
  6. 거리 수정 d.new = d.old + Δd

1D에선 방향만 있으니 +/- 구분만 하면 되는데 2D에선 x축, y축이 있으니까 벡터 개념이 나온다. 어렵게 생각할 것 없이 x성분, y성분 각자 계산하면 된다. f, a, v, d 모두 (x, y) 성분으로 분해된다. 3D에선 (x, y, z) 3개 성분으로 계산하면 된다. 여기까진 쉬운 것이다. 여기까지 내용으로 로켓이나 포탄의 비행을 시뮬레이션 할 수 있다.


에너지 vs 운동량(충격량)


힘, 속도, 거리, 시간, 가속도, 질량은 물리 현상 중에 직관적으로 이해하기 쉬운 개념이다. 에너지는 직관적으로 이해하기 어렵다. 물리학자들도 고민을 많이 한 개념이다. 에너지와 운동량의 개념 차이도 상당이 헛갈린다. 그 차이를 간단하게 설명하겠다.

에너지를 이해하려면 도르래를 이해하면 된다. 물체의 무게가 곧 힘이고, 이 물체를 들어 올리는 높이가 거리이다. 에너지란 힘과 거리의 곱이니 무게와 높이의 곱이 된다. 여기까진 이해하기 쉽다. 이 물체를 잡던 줄을 놓으면? 땅에 떨어질 것인데 이게 운동 에너지다. 이 운동 에너지는 높이 있던 물체에 숨어 있었던 것이다. 높은 곳에 있는 물체는 잠재 에너지가 있는 것이다. 떨어지면서 잠재 에너지가 운동 에너지로 바뀌는 것이다.

자 그러면 공중에 정지하고 있을 때 우리가 알 수 있는 정보는 질량, 높이다. 그리고 떨어진 후에 우리가 알 수 있는 정보는 시간, 속력, 중력 가속도이다. 이 정보들로 서로 호환 가능한 잠재 에너지와 운동 에너지를 수학적으로 표현할 수 있을까? 그렇게 해서 찾아낸 것이 에너지와 운동량 공식이다. 그래서 이 둘의 차이가 뭔지 고민했던 것이다.

그러면 이번엔 낙하 시간을 알고 있으니 힘과 시간을 곱할 수도 있을 것이다. 이것이 운동량이다. 이 잠재적인 운동량도 운동으로 바뀌는데 그게 무게와 속력의 곱이 된다. 에너지 개념보다는 더 직관적으로 이해하기 쉽다. 그럼 왜 운동량 대신 에너지를 사용하는 것일까? 열/빛 에너지와 호환이 되는 건 잠재/운동 에너지다. 그럼 운동량은 필요 없는 개념인가? 운동량과 에너지의 차이는 2차원, 3차원 벡터 합성을 할 때 나타난다. 1차원 운동일 때는 둘의 진짜 차이를 알기 어렵다.



  • 잠재 에너지 = 힘 * 거리 ☞ 무게 * 높이
  • 운동 에너지 = ½ * 질량 * 속력² ☞ ½ * 무게 * 빠르기² ☞ 스칼라
  • 운동 에너지 = 잠재 에너지의 변화량
  • 운동량 = 질량 * 속도 ☞ 무게 * (빠르기 * 방향) ☞ 벡터 (이동은 방향이 있다)
  • 충격량 = 힘 * 시간 = 충격 * 시간 ☞ 벡터 (힘은 방향이 있다)
  • 충격량 = 운동량의 변화량

운동 에너지와 헛갈리는 게 하나 있는데 운동량이다. 속력과 속도의 차이이다. 속력은 단순 빠르기(스칼라)만 의미하고, 속도는 방향까지 포함한 빠르기이다. 이런 것을 벡터라 부른다. 단지 잠재 에너지를 속력으로 바꾸어 표현한 것이 운동 에너지이다. 운동량은 벡터인 속도에 스칼라인 질량을 곱해 운동의 세기와 방향을 표현한 것이다. 그러니까 이 둘은 이름이나 공식 속의 변수가 비슷하다. 그래서 헛갈렸던 것이다.

  • 벡터 : 힘, 가속도, 속도, 거리, 운동량 (벡터 * 스칼라 = 벡터 = 방향성 계승)
  • 스칼라 : 압력, 시간, 질량, 에너지 (벡터 * 벡터 = 스칼라 = 방향성 없음)

잠재 에너지와 헛갈리는 게 하나 있는데 충격량이다. 거리와 시간의 차이이다. 물체를 끌어 올린 거리와 물체를 끌어 올린 시간 차이다. 물체를 너무 빨리 끌어 올리면 충격을 받는다. 즉 짧은 시간에 큰 힘이 가해지면 충격이 크다. 충격량의 원래 뿌리는 운동량이다. 운동하던 물체가 충돌했을 때 저지력(저항력/충격력)과 저지한 거리(에너지), 저지한 시간(충격량)의 차이인 것이다.

파괴력이나 관통력을 계산할 때는 에너지를 이용하고, 벡터 합성 분해를 할 때는 운동량을 이용한다고 생각하면 된다. 즉 X, Y, Z방향 운동량을 벡터 합성하면 총 운동량과 같은데, 각 방향의 에너지를 구한 후에 벡터 합성을 하면 총 에너지와 다르다. 에너지는 따로 계산해서 합성할 수가 없다. 게임에서 운동을 표현할 때는 벡터 합성을 이용하고, 파괴력을 표현할 때는 에너지를 이용한다.



2. 중력과 풍력 추가


앞의 로켓이나 포탄에서 이제 중력과 풍력 등 다른 방향의 힘이 더해진다고 하자. 그럼 벡터 합성이 필요해진다. 에너지는 모두 합성한 후에 최종적으로 계산하는 것이다. 벡터 성분들은 모두 따로 계산해서 합성할 수 있다. 힘, 가속도, 속도, 변위(위치 변화) 모두 벡터라고 했다. 벡터 합성은 쉽다.



포물선은 포탄이 날아가는 곡선을 의미한다. 이 포물선을 계산하려면 단순히 수직, 수평 성분으로 힘을 분해하기만 하면 된다. 수직 성분은 중력 가속도의 영향을 받는다. 3D는 복잡하니까 2D로 가정하자. 수직 방향은 y축, 수평 방향은 x축이라고 놓자. 중력 가속도를 물체의 수직 가속도에 더하기만 하면 된다. 수평 성분은 풍력의 영향을 받는다. 풍력(힘)을 질량으로 나눠 가속도를 구한 후에 수평 가속도에 더하기만 하면 된다. 복잡하게 포물선 계산을 할 필요가 없다. 이렇게 짧은 시간으로 미분(나누기)하여 계산한 후에 적분(누적하기)하면 운동의 묘사가 된다.

가속도 = 엔진 가속도(X, Y) + 중력 가속도(수직) + 풍력 가속도(수평)



3. 인력, 척력, 중력


인력은 당기는 힘, 척력은 미는 힘이다. 중력은 인력에 속하며 보통 2가지로 계산 된다. 땅에 인접한 경우는 땅을 무한 평면으로 보고 중력 가속도 G를 적용한다. 실제 물리에선 9.8이라고 하는데 게임 세계 속에선 임의의 값으로 정한다. 우주로 나가면 그 때는 지구가 작은 공처럼 보이기 때문에 지구 중심에서 거리 제곱에 반비례하는 인력으로 작용한다. 이건 빛이 퍼지는 원리와 같다.


  • 무한 평면 중력가속도 = 상수 ☞ 대기권 안에서 작용하는 중력
  • 무한 원통 중력가속도 = 기준값/거리 ☞ 원심력을 이용한 중력 발생 우주선
  • 원형 지구 중력가속도 = 기준값/거리² ☞ 인공 위성에 작용하는 중력

원심력을 이용한 중력 발생을 하는 우주선의 경우 원심력 = 구심력 = 중력이 된다. 이 경우 구심력 공식(mv²/r)에 의해서 중력은 1/R에 비례하게 된다. 게임에서 쓸 일이 있을까?

표면 장력 같은 인력이나 척력의 경우는 전자기적 힘에 의한 것이기 때문에 거리 제곱(전기장)이나 거리의 3제곱(자기장)과 관련 있다. 그런데 임의로 정해도 된다. 진짜 물리 시뮬레이션은 아니니까.

인력 또는 척력 = 기준값/거리 or 기준값/거리² or 기준값/거리³



4. 마찰력, 저항력, 종단속도


접촉한 물체는 마찰력이 작용하고, 공기 중에선 공기 저항이 작용한다. 잘 생각해 보면 마찰력과 공기저항은 본질적으로 같은 것이다. 그래서 마찰력과 저항력을 구해서 물체의 질량을 나눠 가속도(감속도)를 구한다. 가속도가 음수면 감속도인 것이다. 마찰력과 저항력은 이론적으로 구할 수 있는 값이 아니고 실험적으로 구할 수 있기 때문에 게임에선 마음대로 줘도 된다.

마찰력은 물체의 질량에 비례하고, 방향은 물체의 이동 방향의 반대이다. 저항력은 물체의 속력에 비례하고, 방향은 이동 방향의 반대이다. 물체가 종단 속도에 도달했을 때는 마찰력/저항력과 물체를 가속하는 엔진의 힘/중력과 균형을 이루게 되어 종단 속도를 유지하며 이동한다. 즉, 가속도 0 상태이다.

무거운 것과 가벼운 것은 왜 동시에 떨어질까? 종단속도

  • 마찰력 = 질량 * 비례상수 → 비례상수 = 감속도
  • 저항력 = 속도 * 비례상수
  • 가속도 = 엔진가속도 + 중력가속도 + 풍력가속도 - 마찰감속도 - 저항감속도




5. 강체(고체) 충돌


강체는 고체 중에서 딱딱한 것을 말한다. 쇠사슬 같은 것도 고체에 속하지만 밧줄이나 그물처럼 휜다. 고로 끈이나 천도 고체에 속하지만 강체라고 보긴 어렵겠다. 물렁물렁한 진흙도 고체에 속하지만 강체는 아니다. 강체는 완전탄성충돌을 한다. 완전탄성충돌 공식은 인터넷 검색을 해 보라. 여기에 반발계수(탄성계수)를 적용해서 속도를 약간 감소시키는 방식으로 비탄성충돌을 흉내 낸다. 



충돌을 할 때 충돌면을 계산한다. 이 충돌면에 수직 방향(법선 방향)의 속도만 계산에 동원한다. 수평 방향(접선 방향)은 변화가 없다. 물체 A와 B가 있다. 질량은 Am, Bm이다. 충돌 전 속도는 Av, Bv이다. 충돌 후 속도 Aw, Bw는? 여기서 에너지와 운동량의 협력이 필요하다.
  • Am*Av + Bm*Bv = Am*Aw + Bm*Bw (운동량 보존 법칙)
  • 충돌 전후의 전체 운동량 변화가 없다.
  • Am*Av²+ Bm*Bv²= Am*Aw²+ Bm*Bw² (에너지 보존 법칙)
  • 충돌 전후의 전체 에너지 변화가 없다.

이 두 법칙을 이용해서 충돌 후 속도를 구하면 아래와 같다.
  • Aw = {(Am - Bm)*Av + 2*Bm*Bv}/(Am + Bm)
  • Bw = {(Bm - Am)*Bv + 2*Am*Av}/(Am + Bm)
  • 충돌후속도 = {질량차이*충돌전속도 + 2*상대방운동량}/전체질량
  • Aw = {(Am*Av + Bm*Bv) + Bm(Bv - Av)}/(Am + Bm)
  • Bw = {(Am*Av + Bm*Bv) + Am(Av - Bv)}/(Am + Bm)
  • 충돌후속도 = {충돌전 운동량 합 + 상대방질량(충돌전 속도차))/전체질량
  • (Aw – Bw) = (Bv – Av) ☞ 충돌 전후의 상대 속도는 같고 방향만 반대
  • (Aw + Av) = (Bw + Bv) ☞ 충돌 전후의 속도 합이 같다

여기서 상대 속도에 대해서도 계산이 통하기 때문에 기준 속도를 뺀다고 하면?
  • (Am + Bm)Aw = {(Am - Bm)*Av + 2*Bm*Bv} 수식은 다음처럼 변경
  • (Am + Bm)(Aw - Av) = 2*Bm(Bv - Av) @ Av = 기준 속도
  • (Am + Bm)(Aw - Bv) = (Am - Bm)(Av - Bv) @ Bv = 기준 속도

여기서 기준 질량을 나누어 준다고 하면? 상대 속도, 상대 질량으로 계산 가능
  • (1 + R)(Aw - Av) = 2*R(Bv - Av) @ 자기 Av, Am 기준, R = Bm/Am
  • (R + 1)(Aw - Bv) = (R - 1)(Av - Bv) @ 상대 Bv, Bm 기준 R = Am/Bm

여기서 상대방 기준으로 계산한 경우 자신의 충돌 전후 상대 속도 변화를 구할 수 있다.
  • 상대 Bv, Bm 기준 Rm = Am/Bm, Rv = (Aw-Bv)/(Av-Bv)
  • Rv = (Rm-1)/(Rm+1) @ -1 < Rv < 1 
  • Rm = (1+Rv)/(1-Rv)
  • 질량의 비율이 같다면, 상대 속도의 변화 비율도 같다.

자기 기준일 때는 다음과 같은 꼴이다. (상대가 와서 박을 때)
  • 자기 Av, Am 기준 Rm = Bm/Am, Rv = (Aw-Av)/(Bv-Av)
  • Rv = 2Rm/(1+Rm) = (Rm+Rm)/(Rm+1) @ 0 < Rv < 2
  • Rm = Rv/(2-Rv)
  • 상대방 기준의 경우에서 +1을 한 것과 같다.

상대 값으로 계산한 후에 절대 값으로 환산하는 게 쉽다

위의 그래프 해석은 이렇다.
  • 상대가 너무 가벼운 경우 나는 속력을 거의 잃지 않고, 상대는 튕겨 나간다. 즉 에너지를 거의 전달하지 못 한다. 더 밀고 싶어도 못 밀어 준다.
  • 상대가 너무 무거운 경우 상대는 거의 움직이지 않고, 내가 반대로 튕겨 나간다. 즉 에너지를 거의 전달하지 못 하고 돌려 받는다. 벽과의 충돌에 해당.
  • 상대와 내가 비슷한 무게인 경우, 에너지는 그대로 전달 된다. 나는 멈추고, 상대는 그대로 같은 속도로 튕겨 나간다.

여기서 충돌 후 속도를 구한 후에 반발 계수에 따라 속도 감속을 한다.
  • e = -(Aw - Bw)/(Av - Bv) = -충돌후속도차/충돌전속도차, 0<e<1
  • 반발계수가 1이면 완전탄성충돌, 0이면 떡처럼 붙어 버린 경우

예를 들어 e = 50%라면 충돌후 속도를 50% 줄이면 된다. 이렇게 구한 법선 방향 속도를 접선 방향과 다시 합성한다. 벡터 합성은 서로 직각이니 피타고라스 정리를 사용한다.

자 그러면 법선 방향만 추출하는 방법을 또 알려 달라고 하겠지? 이런 경우 물체의 형상을 단순화시켜야 한다. 형상이 복잡하면 충돌 지점을 계산하기도 힘들고 복잡한 회전도 함께 발생한다. 그래서 원형이 가장 쉬우니 원형이라고 가정한다. 원형이라도 회전은 발생하지만 무시하자. 원과 원의 중심선을 이으면 그게 법선이다. 이것과 수직인 것이 접선이다.



속도/좌표는 이미 (X, Y) 성분으로 분해되어 있을 것이다. 방향 벡터(두 구체의 중심 좌표 차이)를 구하면 그게 바로 법선 벡터이다. 이 법선 벡터의 X, Y 값을 서로 바꾸면 그게 접선 벡터이다. 법선 방향 속도는 법선과 속도의 벡터 내적(스칼라곱/점곱)을 취하면 얻어진다. 공식은 위와 같다. 법선과 접선 벡터는 기준이 되기 때문에 어느 방향이든 상관없으니 하나로 통일하면 된다. 두 물체 중에 어느 하나가 기준이 되면 된다.

접선 방향의 속도 차이가 있게 되면 그게 표면 마찰을 일으켜서 회전력으로 작용한다. 그럼 어느 정도 회전이 발생할까? 이건 계산이 복잡하다. 물체의 이동과 회전 사이의 에너지/운동량 변환이 필요한데 공식을 모르겠다. 회전이 발생한 만큼 이동하는 에너지와 운동량이 줄어야 한다. 원형 물체의 경우 이동에선 모든 질량이 중심에 있다고 가정하고, 회전에선 모든 질량이 표면에 있다고 가정하고 계산한다. 여기까지만...




당구공의 충돌이라고 할 경우 충돌 지점의 접선, 접면을 계산해야 한다. 그래서 법선, 접선 방향을 구분해서 법선 방향에 대해서만 위의 충돌 공식을 적용할 수 있다. 간단하게 이 문제를 이해하려면 당구공과 수직, 수평의 무한 질량을 가진 당구대 벽과의 충돌을 상상하면 된다. 벽이 수직과 수평 방향으로 서 있기 때문에 충돌 지점의 법선과 접선이 수평, 수직 방향으로 단순해진다.

이 경우 법선에 대해서만 위의 공식을 적용하면 되기 때문에 간단하다. 벽의 질량이 무한이고 속도는 0이다. 고등학교 수학을 생각하며 잘 계산해 보면 법선 방향의 속도가 반대가 되어 튕겨 나오는 것을 알 것이다. 그래서 수직, 수평 장벽과 충돌은 의외로 간단하게 계산 된다. x방향, y방향의 속도 중에 하나의 부호만 뒤집으면 된다. 여기까지 내용으로는 당구 게임을 흉내 낼 수 있다. 



6. 액체의 부력, 기체의 양력


액체의 경우는 형상이 없는 점으로 계산한다. 이 점은 인접한 점과의 거리에 따라 인력(표면 장력)이 작용한다. 어느 정도 거리 밖에선 위와 같은 탄성 충돌로 계산하고, 어느 거리 안에선 표면장력이란 것이 작용하기 때문에 약간의 인력을 추가한다. 그리고 어떤 거리 안에선 무한대의 척력을 내서 압축이 되지 않도록 한다. 액체는 고체와 마찬가지로 압축이 안 된다. 액체는 유동적인 고체라고 보면 된다.

중력 구간(원거리) ~ 인력 구간(근거리) ~ 척력 구간(입자 내부)

부력의 경우는 물체가 밀어낸 액체의 양의 무게와 물체 자체의 무게를 비교해서 그 차이만큼 힘이 작용하게 된다. 물체가 표면에 떠 있을 때는 부력이 0이 된 상태이다. 가라앉은 부분만큼의 물의 양이 물체의 무게가 된다. 부력은 중력의 반대 방향이다.

물에 빠지는 순간 물과의 마찰로 에너지/운동량을 잃기 때문에 가라앉았다가 솟아오르기를 무한 반복할 수는 없다. (탄성 충돌 참고) 액체 속에서 이동은 마찰력으로 속도 손실을 가져온다. (종단 속도 참고)

힘과 압력의 차이, 벡터와 스칼라, 삼투현상 & 모세관현상


부력 = (액체 무게 – 물체 무게)

물체와 물의 무게 비교는 비중을 보면 안다. 물은 비중이 1이고 기준이다. 1㎥부피는 1톤, 10㎤=1ℓ 부피는 1kg, 1㎤ 부피는 1g이다. 기체의 경우는 1㎥ 부피에 1g이라고 생각하면 된다. 



7. 기체와 스프링과 와이어


기체의 경우도 형상이 없는 점으로 계산한다. 이 기체의 경우는 스프링처럼 압축이 된다. 그리고 표면장력 같은 점성이 없다. 고로 척력만 있는 경우에 해당하며 완전탄성충돌을 한다. 기체는 중력의 영향을 받지만 일상 생활공간에선 중력의 영향을 받지 않는 것으로 처리한다. 이런 기체를 시뮬레이션 할 경우는 없을 것이다.

코일 스프링은 단순하다. 당기거나 압축시킨 길이에 비례하여 힘이 나온다. 그래서 힘 측정기로 사용하기도 한다. 이런 특징을 선형적이라 한다. 기체의 경우는 압력이 부피에 반비례하기 때문에 비선형적이다. 코일 스프링 시뮬레이션은 쉽다. 판 스프링은? 몰라.

스프링 변형 길이 = 힘

실, 밧줄, 쇠사슬, 그물, 천 같은 것은 고체일까? 고체이다. 작은 고체들이 쇠사슬처럼 엮여 있다고 생각하면 된다. 이런 것들은 점과 점 사이의 직선으로 표현한다. 이 직선이 스프링처럼 탄성이 있으면 고무줄이 된다. 문제는 엮여 있어서 힘이 전파되기 때문에 연쇄반응으로 계산이 많아진다. 이런 거 해 주는 라이브러리(누군가 만들어 제공하는 함수들) 많다.

A를 치면? → B → C → D → ... 계산법은? 몰라

그럼 불은 뭘까? 화학반응이다. 화학 반응을 구현하는 건 내 수준을 넘는다. 화학 반응이란 a와 b가 만나서 하나로 합쳐지면서 열과 빛을 내고 부피가 커지는 반응이다. 그러니까 합성된 기체(CO₂나 H₂O 등)의 운동량이 증가하며 빛과 열을 내며 터진다는 것이지.


8. 회전(토크)


물체는 충돌할 때 회전도 한다. 그럼 에너지, 운동량, 각운동량, 토크 사이의 변환이 필요할 것인데 여기엔 답이 없다. 이걸 제대로 계산하려면 물체 형상에 따라 적당한 미분 적분을 해야 한다. 그럴 시간이 없으니까 물체의 형상을 단순화해야 한다. 원, 공, 정사각형, 정육면체(입방체) 등으로 말이다. 이런 물체는 회전 중심(무게 중심)이 정확하게 가운데 있고 대칭적이다. 충돌 지점도 단순화시키기 위해서 원, 공으로 계산한다.

충돌 순간에 에너지와 운동량의 어느 정도가 회전으로 전환될지 계산이 어려우니 물체의 질량과 크기(반지름)만 가지고 임의로 회전을 주는 방법도 있겠다. 이건 너무 골치 아프다. 회전에선 저울/톱니/바퀴 시뮬레이션도 필요하기 때문에 토크 개념은 알고 있어야 한다.




  • t = r*f (토크 = 반지름 * 힘)
  • w = r*m*v (각운동량 = 반지름 * 운동량)

위의 공식은 모든 질량이 표면 껍질에 몰려 있고 형상이 원, 공인 경우로 가정한 것이다. 형상이 복잡한 물체는 무게 중심 계산도 힘들다. 예를 들어 무게가 1과 2인 물체를 저울에 올리면 저울의 팔은 반대로 저울 중심(무게 중심)에서 2와 1의 길이가 되어야 한다. 반지름이 1과 2인 톱니가 서로 맞물려 돌아갈 때 회전 속도는 반대로 2대 1이 된다. 도르래도 저울과 원리가 비슷하다. 무게와 길이 사이의 관계이다. 

저울이 중심을 잡기 위해 위아래로 흔들리는 현상을 알 것이다. 이런 원리는 무게 중심의 이동에 있다. 저울의 중심을 잡아주는 접촉점은 이상적인 점이 아니다. 면적이 있는 물체 표면이기 때문에 저울 팔이 기울면서 접촉면도 살짝 이동을 한다. 그래서 무게 중심이 이동하기 때문에 반대로 균형을 잡으려는 힘이 작용하게 되는 것이다. 게임에선 임의의 값으로 지정해 줄 수 있다.

만약 반대 방향으로 회전하는, 무게와 회전 속도가 다른 두 팽이가 충돌하게 되면 어떻게 될까? 회전 방향은 접선 방향이다. 접선 방향의 에너지/운동량을 잃은 만큼 회전이 바뀐다. 그럼 얼마가 이동으로 빠지고, 얼마가 회전으로 빠질까? 계산 공식은 모르겠다. 포기! (대학교 물리학 책을 보면 되잖아? 아니면 라이브러리를 구해서 사용하면 되겠지?) 법선 방향에 작용하는 힘은 마찰력에 비례한다. 이 마찰력에 의해 접선 방향의 속도가 영향을 받는다. 마찰력은 서로가 접촉해서 미는 힘에서 온다.




9. 거리 계산 → 충돌 계산


충돌을 계산하려면 근처에 있는 것인지 아닌지 구분부터 해야 한다. 충돌은 거리와 크기에 관계있기 때문이다. 지구 반대편에 있는 물체와 충돌 검사를 하는 것은 의미 없을 것이다. 100개의 물체 사이의 거리를 계산하려면 약 100²/2 = 5000번의 비교 계산을 해야 한다. 이건 너무 비효율적이다.

게임 공간을 적당히 사각형으로 나눈다. 그 공간에 속하는 물체는 그 공간에 자신을 등록한다. 그래서 그 공간 주변(3x3블록)에 속하는 것들끼리만 거리 계산을 해 보고 충돌 가능성이 있는 것들끼리 충돌 검사를 한다. 즉 멀리 있는 다른 세계의 물체는 충돌 검사가 필요 없다.

이건 물체의 수가 많을 경우에 그렇게 한다는 것이고 물체의 수가 적을 때는 모든 물체끼리 거리 계산을 다 해도 된다. 그리고 충돌 가능성이 있는 것에 대해선 충돌 검사를 한다.

충돌 검사는 형태와 관계있기 때문에 역시 형태를 단순한 원, 공, 정사각형, 입방체로 보는 것이 편하다. 원, 공은 중심 사이의 거리를 계산하면 된다. 3D에서도 계산이 가장 쉽다. 정사각형, 입방체의 경우는 어느 한 개를 기준으로 회전시켜 x, y, z축을 일치시킨 후에 복잡한 계산을 해야 한다. 만약 x, y, z축이 항상 일치하는 경우에는 충돌 검사가 쉽다. 그런 경우가 정사각형, 정마름모이다. 
  • 원의 충돌 : dx² + dy² < (Ra + Rb)²
  • 정사각형 충돌 : dx and dy < Ra + Rb
  • 정마름모 충돌 : dx + dy < Ra + Rb
원의 경우 충돌 계산과 거리 계산 공식이 같다. 그래서 한 번의 계산으로 거리 계산과 충돌 여부 판단이 가능하다. 정사각형이나 정마름모의 경우는 물체의 형상이 원형이 아닌 건물 같은 경우에 적용한다. 먼저 원형으로 보고 거리 계산을 한 후에 충돌 가능한 거리에선 정사각형과 정마름모로 다시 계산을 한다. 그러니까 역시 원형이 가장 기본이 되는군.




같은 형태가 아닌 서로 다른 형태인 원과 정사각형의 충돌을 계산한다고 할 경우 사각형은 4개의 선으로 되어 있으니 원과 4개 직선의 접선, 교점 구하는 문제가 된다. 3D에선 접선이 접면이 되고 교점이 교차선이 된다. 원보다는 사각형을 기준 좌표로 보고 축을 회전하여 x, y에 맞추고 계산하는 것이 더 쉬울 것이다. 원은 회전을 해도 원이기 때문이다.

이렇게 하면 사각형의 모든 직선은 x, y축에 수직이거나 평행하게 된다. 그럼 계산이 쉬워지지. 회전 공식을 알아야 하겠군. 인터넷 검색! 사각형의 꼭짓점이 원과 접촉한 경우는 반대로 원을 중심으로 4개 꼭짓점이 원의 안에 있는지 검사하는 것으로 충돌 검사를 할 수 있다. 
  • 2D 선의 공식 → 3D 면의 공식
  • 2D 원의 공식 → 3D 구의 공식
2D에서 3가지 형태의 직선 공식 → 3D에서 3가지 형태의 평면 공식
  • y = a*x + b → z = a*x + b*y + c
  • a*x + b*y = c → a*x + b*y + c*z = d
  • x/a + y/b = 1 → x/a + y/b + z/c = 1

위에서 2D에서 선을 표현하는 것은 3D에선 면이 되었다. 그럼 3D에서 선은 어떻게 표현 하냐? x-y, y-z, z-x 사이의 관계 3개를 통해서 표현한다. 다시 말해서 xy, yz, zx 3면에서의 직선 공식으로 3D에서 직선을 표현한다. 보통은 벡터(좌표 A ~ 좌표 B)로 표현하면 쉽다.

3D로 가면 머리가 복잡하고 복잡한 모양의 물체의 충돌과 회전을 처리하기는 힘들다. 여기까지 내용으로는 포탄의 포물선 시뮬레이션이나 원, 공의 충돌 정도만 처리할 수 있을 것이다. 원, 공을 사용하면 일단 회전 문제를 신경 쓰지 않아도 되니 좋다. 더 이상 공부해도 진전이 없는 바보짓이니 여기서 그만 하자.

3D 문제 → 2D 문제 → 1D 문제로 분해하여 푼다.




우리 사랑스런 친일독재잔당은 토목공사를 좋아한다. 그래서 강바닥, 길바닥에 돈을 뿌린다. 멀쩡한 강물 막아 오염시키고, 사람이 살지도 않을 곳에 건물을 짓고, 차가 다니지도 않을 곳에 도로를 깐다. 이미 유럽 → 미국 → 일본에서 했던 세금 낭비 정책 아닌가? 그 돈을 복지에 썼더라면 많은 사람이 행복했을 것인데.

거기에 증세 없이 복지 하겠다는 새빨간 거짓말을 하고 (이게 무슨 헛소리인가?) 결국 담배 값 올리고 복지는 없지. 거기에 철도 민영화(사유화)로 교통비만 비싸게 올리려 하고. 이것도 이미 다 유럽 → 미국 → 일본에서 했던 국민 기만 정책 아닌가? (일본에 가니 교통비가 비싸더라, 유럽에 가니 공항료가 너무 비싸더라. 모두 민영화 된 곳이다.)

게임 산업은 핍박을 하지. 그런데 게임이 장기, 바둑, 카지노와 뭐가 다른가? 지역 경제 살리려고 카지노 하는 것이지? 그럼 게임으로 먹고 사는 사람들 밥줄 끊는 짓은 왜? 직업을 만들지 않고 없애는 이유가 뭐냐? 이명박근혜가 이런 수준이면서 왜 그렇게 김대중, 노무현 욕했냐? 말년까지 욕먹을 각오해라.

수 천 년 동안 정부가 해야 할 일은 뻔히 정해져 있었다. 성경, 불경, 유교 경전에 다 나오는 내용이다. 그걸 하면 충신(천사)이고 하지 않으면 간신(악마)이다.

댓글 1개:

  1. 쩔어요 원과 원 충돌후 속도 방향을 어떻게 처리해줘야할지 3일동안 머리쥐어뜯고있었는데
    여기 다 정리되있네요 감사합니다!!

    답글삭제