Quais métodos de simulação física são mais adequados para um tempo delta realmente grande (horas a semanas)?
Além disso, enfrentaria problemas ao combinar diferentes métodos para grandes e pequenos tempos delta?
Quais métodos de simulação física são mais adequados para um tempo delta realmente grande (horas a semanas)?
Além disso, enfrentaria problemas ao combinar diferentes métodos para grandes e pequenos tempos delta?
Respostas:
Você provavelmente usará aceleração constante para esses períodos de tempo grandes (que podem ser aceleração zero). A derivada da aceleração constante em relação ao tempo é 0. Isso significa que não muda em relação ao tempo, portanto, não importa o tamanho do seu tempo delta.
Essa pequena integração com relação ao tempo fornece as equações necessárias.
a = a
v = at + v0
s = .5at^2 + v0*t + s0
Onde: a = aceleração, v = velocidade, v0 = velocidade inicial, s = posição, s0 = posição inicial, t = tempo
Usando essa estratégia, você pode usar períodos de milissegundos a semanas, se desejar. Combiná-los seria resolvido nos parâmetros v0
e s0
da equação.
Para lidar com colisões, você precisará implementar estratégias semelhantes às usadas para objetos pequenos de alta velocidade . Primeiro calcule a nova posição usando a equação acima e depois varra entre a posição antiga e a nova para todos os objetos. Como qualquer um desses objetos pode ter se cruzado (minutos ou dias antes), isso pode se tornar muito complexo. É provável que, como você tenha um período delta tão grande, espere ter tempo de sobra para processar essas possíveis colisões.
Vamos dar um exemplo com gravidade.
Na função abaixo, assuma que temos variáveis de membro de classe para posição e velocidade. Precisamos atualizá-los devido à força da gravidade a cada dt segundos.
void update( float dt )
{
acceleration = G * m / r^2;
velocity = velocity + acceleration * dt;
position = position + velocity * dt;
}
À medida que dt
cada vez menores, nossa simulação se torna cada vez mais precisa (embora, se dt
for pequena demais, podemos encontrar erros de precisão ao adicionar números pequenos a grandes).
Basicamente, você precisa decidir o máximo que dt
sua simulação pode suportar para obter bons resultados. E se o dt
que entra é muito grande, basta dividir a simulação em etapas menores, onde cada etapa é o máximo dt
que você permite.
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
}
Portanto, com essa estratégia, você pode simplesmente se ajustar timeStep
à fidelidade necessária (espere um segundo, minuto, hora ou o que for necessário para obter uma representação precisa da física.
A maioria dos jogos costuma usar o simples método Euler de integração direta (ou seja, integrar a velocidade na posição ao longo do tempo e integrar a aceleração na velocidade). Infelizmente, o método Euler é adequado apenas para escalas de tempo muito pequenas e tiragens curtas.
Existem métodos mais complexos que são mais precisos em escalas de tempo muito longas. O mais popular e mais fácil de implementar é talvez Runge-Kutte-4 . O RK4 determina a posição no futuro, amostrando quatro posições e velocidades no passado e interpolando. Ele tende a ser muito mais preciso que o método Euler em escalas de tempo mais longas, mas é mais caro em termos computacionais.
Por exemplo, se você quiser calcular a física de um planeta em órbita real, atualizando a cada poucos dias em tempo real, o método Euler fará com que o planeta caia no espaço depois de apenas algumas órbitas devido a erros numéricos. O RK4 geralmente mantém o planeta em órbita quase da mesma forma milhares de vezes antes de acumular muitos erros.
No entanto, implementar colisões no RK4 pode ser muito desafiador ...