델타 시간이 큰 물리 시뮬레이션 방법?


9

실제로 큰 델타 시간 (시간-주)에 가장 적합한 물리 시뮬레이션 방법은 무엇입니까?

또한 델타 시간이 크고 작은 다른 방법을 결합하는 데 문제가 있습니까?


1
그것은 주로 목표 지역에 달려 있습니다. 실제 목표에 대해 더 많이 알지 못하면 아무 말도하지 않습니다. 너무 넓은.
Kromster

이 질문 은 관련이 있습니다.
Anko

원칙적으로 적절한 시간 척도는 플레이어가 경험하는 것에 달려 있습니다. 당신이 주간의 시간 척도에 대한 정확한되고 싶어 하고 실시간으로 그것으로 플레이어의 상호 작용이? 플레이어가 실시간으로 여러 번 경험하는 주 단위의 시간 단위로 작업하는 것보다 훨씬 어렵습니다 ( , 플레이어 경험의 1 초는 1 주일의 실시간입니다).
mklingen

구름 운동 또는 수백 미터 너비의 셀에서 열역학적 변수를 시뮬레이션하는 경우 dt가 10 분이면 합리적입니다. 그러나 평소 비늘의 강체는 그리 크지 않습니다. 응용 프로그램은 무엇입니까?
v.oddou

응용 프로그램은 (일부 세계의) 마지막로드 이후 시뮬레이션이 실행되는 "캐치 업"메커니즘이며, 게임 로직은 콜백이 타이머 또는 충돌 콜백 인 모든 콜백 기반이며, 다음에 물리를 실행할 수 있기를 원합니다 타이머 콜백을 효율적으로 수행하고 물리 시뮬레이션으로 콜리 전 콜백 호출을 처리합니다. 충돌은 상대적으로 쉽지 않지만 충돌시 콜백이 사용 가능한 게임 (물리) 상태를 갖기를 원합니다.
fread2281

답변:


5

이러한 큰 시간 범위 (제로 가속 일 수 있음)에 일정한 가속을 사용하고있을 것입니다. 시간에 대한 일정한 가속도의 미분은 0입니다. 이는 시간에 따라 변하지 않기 때문에 델타 시간이 얼마나 큰지는 중요하지 않습니다.

시간에 대한이 작은 통합은 필요한 방정식을 제공합니다.

a = a
v = at + v0
s = .5at^2 + v0*t + s0

여기서 : a = 가속, v = 속도, v0 = 초기 속도, s = 위치, s0 = 초기 위치, t = 시간

이 전략을 사용하면 원하는 시간을 밀리 초에서 몇 주까지 사용할 수 있습니다. 그것들을 결합 하면 방정식 의 v0s0매개 변수에서 처리됩니다.

충돌을 처리하려면 구현해야합니다 고속 소형 물체에 사용되는 것과 유사한 전략 합니다 . 먼저 위의 방정식을 사용하여 새 위치를 계산 한 다음 모든 객체에 대해 이전 위치와 새 위치를 스윕합니다. 이러한 개체 중 하나가 서로 교차 할 수 있기 (분 또는 몇 일 전) 매우 복잡 할 수 있습니다. 델타 시간이 길기 때문에 이러한 잠재적 충돌을 처리 할 시간이 충분할 것입니다.


충돌은 어떻습니까?
fread2281

충돌 처리 전략을 포함하도록 답변을 업데이트했습니다.
마이클 하우스

이것은 거짓입니다. 오일러 통합은 지속적인 통합을 위해 벗어나는 반면, Verlet (또는 RK2, RK4)은 그렇지 않습니다.
v.oddou

@ v.oddou 이러한 시뮬레이션이 게임을위한 것이라는 점을 고려할 때 필요한 정확도가 필요하다고 생각하지 않습니다. Verlet에 충돌을 추가하는 데 따른 복잡성과 난이도는 오일러 통합을 탁월한 선택으로 만듭니다.
MichaelHouse

2

중력을 예로 들어 보겠습니다.

아래 함수에서 위치와 속도에 대한 클래스 멤버 변수가 있다고 가정합니다. 우리는 매 dt 초마다 중력으로 인해 그것들을 업데이트해야합니다.

void update( float dt )
{
   acceleration = G * m / r^2;
   velocity = velocity + acceleration * dt;
   position = position + velocity * dt;
}

dt점점 작아 지면서 시뮬레이션은 더욱 정확 해집니다.dt 너무 작아지면 작은 숫자를 큰 숫자에 추가 할 때 정밀 오류가 발생할 수 있음).

기본적으로 dt충분한 결과를 얻기 위해 시뮬레이션이 처리 할 수 있는 최대 값을 결정해야 합니다. 그리고 dt그것이 들어오는 것이 너무 크다면, 시뮬레이션을 더 작은 단계로 나눕니다. 각 단계는 dt허용 되는 최대 값 입니다.

void update( float dt )
{
   acceleration = G * m / r^2;
   velocity = velocity + acceleration * dt;
   position = position + velocity * dt;
}

// this is the function we call. The above function is a helper to this function.
void updateLargeDt( float dt )
{
    const float timeStep = 0.1;
    while( dt > timeStep   )
    {
        update( timeStep  );
        dt -= timeStep ;
    }

    update( dt );  // update with whatever dt is left over from above
}

따라서이 전략을 사용 timeStep 하면 필요한 충실도에 맞게 조정할 수 있습니다 (물리를 정확하게 표현하는 데 필요한 초, 분, 시간 또는 무엇이든).


1

대부분의 게임은 간단한 오일러 를 사용하는 경향이 있습니다 순방향 통합 방법 (즉, 시간에 따라 속도를 위치에 통합하고 가속도를 속도에 통합). 불행히도, 오일러 방법은 매우 작은 시간 단위 및 단기 실행에만 적합합니다.

매우 오랜 시간 동안 더 정확한 더 복잡한 방법이 있습니다. 가장 인기 있고 구현하기 가장 쉬운 것은 아마도 Runge-Kutte-4 일 것입니다 입니다. RK4는 과거의 4 가지 위치와 속도를 샘플링하고 보간하여 미래의 위치를 ​​결정합니다. 더 긴 시간 단위에 걸쳐 Euler 방법보다 훨씬 더 정확한 경향이 있지만 계산 비용이 많이 듭니다.

예를 들어 며칠마다 실시간으로 업데이트되는 실제 궤도 행성의 물리학을 계산하려는 경우 오일러 방법을 사용하면 숫자 오류로 인해 몇 번의 궤도 후에 행성이 우주로 발사됩니다. RK4는 일반적으로 너무 많은 오차를 축적하기 전에 행성 궤도를 수천 번에 걸쳐 거의 같은 모양으로 유지합니다.

그러나 RK4에 충돌을 구현하는 것은 매우 어려울 수 있습니다 ...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.