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


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 = 시간

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

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


충돌은 어떻습니까?
— 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.