게임 개발 이야기: 속도를 계산 하는 방법 how to calculate velocity in game enginesteemCreated with Sketch.

in #kr-dev7 years ago (edited)

게임 엔진에서 물체는 일반적으로 강체로 표현됩니다. 강체(rigid body)는 물체에 힘을 가해도 형상이 변하지 않는 물체를 말합니다. 일반적으로 물체는 스프링과 같아서 힘을 가하면 압축되었다가 힘이 사라지면 원래대로 돌아오거든요.

an object are normally treated as a rigid body in game engine for physical calculations. if an object is a rigid body, it means that the object can not deformed by forces acting on the object. In real world the most objects are kinds of spring. they are compressed when a force is acting on them, then it recover its original form when the force is released.

그런데 야구공을 던질때 야구공에 작용하는 힘에 의한 변형이 거의 없으니 이걸 계산해봐야 그 변형된 단면에 대한 공기저항의 변화의 크기도 고려할 가치도 없이 작겠지요. 그래서 강체로 가정하고 계산해도 무리가 없습니다.
let assume a ball is in play and a programmer want simulate the effect of changing drag force from the deformation. the deformation is so small so the change in the drag force is negligible. that's why one can safely consider the ball as rigid body.

물리 엔진은 속도를 계산할 때, 물체에 작용하는 힘으로부터 계산 합니다. 물체에 작용한 힘에서 가속도를 계산 할 수 있으니까요. (F = m*a)

가속도 a = F/m 인걸 알았으니 속도는 v = v0 + a*t 라는 공식으로 계산하는건 너무 당연하겠죠. 하지만 저 식은 a가 일정한 경우에만 쓸 수 있습니다. a가 시간에 따라 변한다면 당연히 쓸 수 없습니다.

the most physical engines calculate velocities from the total external forces of an object. because of F=ma. the formula v = v0 + a*t is trivial. but the limitation is that a is constant in time if not? of cause you can't use it.

하지만 어짜피 프로그래머들은 매 프레임마다 가속도를 계산하니까 사실 별 문제는 없습니다.

코드로 쓴다면 이렇게 하겠죠?
but programmers usually calculate the acceleration at every single frame. the limitation isn't the case. In python code, the velocity is calculated as following:

for i in range(TIME):
    a = F[i]/m
    v_new = v[i] + a*dt
    v.append(v_new)



그런데, 위 식이 원래 어떤 모양이었는지가 더 재밌는 부분 입니다.
the fun part is the original form of the code.

다시 F=ma 로 돌아가서, F = ma는 F = m*dv/dt 라는 미분이 포함된 식으로 포함됩니다.

dv/dt 는 v를 시간 t에 대해 미분한 것이니 가속도는 해당 시간의 가속도이지 프로그래머들이 계산할 때 쓰는 한 프레임 시간동안의 평균 가속도를 의미하는건 당연히 아니겠죠.

Back to F=ma, F=ma is equal to F = m*dv/dt which has a derivative. dv/dt is an acceleration of a certain time, not the average acceleration along the period like a frame.

가속도를 dt 시간 동안의 기울기로 나타내는 수학적인 방법이 있죠. 바로 테일러 급수.
Taylor series can transform the acceleration to the average acceleration for dt.

f(x) = f(a) + f'(a)(x-a) + f''(a)(x-a)^2/2 + ...

속도 v를 테일러 급수로 나타낸다면 다음과 같습니다.
v as a tylor series is represented as following,

v(t) = v(a) + v'(a)(x-a) + v''(a)(x-a)^2 /2 + ...

위의 표현을 빌리면, 가속도 a = v' 니까 이렇게 표현됩니다:
so, the acceleration a = v' and v' is following

v'(a) = {v(t)-v(a)}/(x-a) - v''(a)*(x-a) /2 - ...

뒤에 -v''(a)*(x-a)/2 - ... 이 부분은 그냥 오차라고 하고 O(dt) 이렇게 표현합니다.

the part -v''(a)*(x-a)/2 -... is called as error, which is O(dt)

그러니까 현재 시간 i 일 때, dt 시간 후의 속도는 이렇게 됩니다.
finally we get the mathematical form of the code.

v(i+dt) = v(i) + dt * v'(i) + O(dt)

이런 과정을 이산화discretization 이라고 하고 컴퓨터로 풀기 어려운 미분 방정식을 프로그래밍하기 쉬운 다항식으로 바꾼 과정 입니다. 프로그래머들은 이런 과정을 자연스럽게 하고 있습니다.

참고로 각도가 0도에 가까울 때, sin(x) 함수를 x로, cos(x) = 1 이라고 가정하는 이유도 바로 테일러 급수에 의한 것 입니다. sin(x)의 테일러 시리즈를 구하고, a에 0을 넣어보면 확인 할 수 있습니다(이 급수를 맥놀린 급수라고도 합니당)

this process changing a derivative to a polynomial is discretization. many difficult differential equations are solved by the numerical method. this is the way programmers doing unconsciously.

plus, when an angle is very close to 0, sin(x) and cos(x) are assumed as x and 1. it's also because of Taylor series. you can see it from Taylor series of sin(x) and cos(x) plugging a =0 (Taylor series with a = 0 is called as Maclaurin series)

그냥 평소에 별 생각 없이 속도 계산하고 있다가 아 저게 테일러 급수였지 ... 라는 생각이 들어서 정리했습니다. 이산화를 잘하는 사람들은 미분 방정식에서 쉽게 수치해석까지 이끌어가시더라구요.

I used to calculate the velocities and popped it was a Taylor series. people who are good at discretization can easily build a simulations from differential equations.

Sort:  

아래처럼 되는데, 뭐가 잘못된거죠?

v[i+1] = v[i] + v'[i]*dt
v[i+2] = v[i+1] + v'[i]*dt
       = v[i] + v'[i]*dt + v'[i]*dt
       = v[i] + 2*v'[i]*dt
v[i+n] = v[i] + n*v'[i]*dt

댓글과 같은 경우라면,

v[i+2] = v[i+1] + v'[i+1]*dt
       = v[i] + v'[i]*dt + v'[i+1]*dt

가 되어야 합니다. v'[i] 는 위 코드에서 a에 해당하므로 a가 변경된다면 v'[i+1] != v'[i] 일 수 있거든요 ....

아 그런데 예제 코드론 F가 상수로 보이기 때문에 nv'[i]dt 라고 결론 내리신게 맞습니다;; 코드 수정하겠습니다 ㅠ.ㅠ

좋습니다~~~ 머리를쓰게 하네요~

취미지만 게임 개발이 지겨울때마다 저런 것들을 보고 있는데 게임 만드는 것보다 더 재밌는 것 같습니다.

Congratulations @emalron! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes
Award for the number of posts published
Award for the number of comments

Click on any badge to view your own Board of Honnor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!