Como faço para corrigir objetos "estalando" ou tremendo no mecanismo de física?

11

Eu tenho um mecanismo de física simples que resolve colisões simplesmente corrigindo a posição de corpos sobrepostos (apenas círculos por enquanto) diretamente, em vez de apenas mudar a velocidade ou aplicar um impulso. A velocidade é alterada somente depois que os impactos já estão resolvidos ou durante a parte de integração.

Eu tive o problema de que, em montes de objetos, os objetos principais aplicam muita pressão (isso existe implicitamente, não há modelagem de pressão no algoritmo) nos objetos na parte inferior da pilha, o que resulta em serem empurrados pelos pisos, etc.

Eu queria consertar isso classificando os objetos pela coordenada y, para que as colisões fossem resolvidas de baixo para cima. Mas agora, o mecanismo mostra um comportamento estranho de popping para objetos que realmente deveriam estar em repouso (veja gif)

insira a descrição da imagem aqui

Sem apenas fornecer o código-fonte - o que poderia ser isso?

TravisG
fonte
5
Em suma, isso é semelhante à solução de um sistema linear de equações de maneira iterativa (ou sistema não linear, dependendo de suas restrições / condições / etc). Em ambos os casos, você está vendo esses artefatos porque eles são numericamente a coisa correta a se ver: estados intermediários de um processo de convergência. Evitar isso é bastante difícil e pode implicar muitos hackers desagradáveis ​​(de qualquer forma, isso acontece na vida real, em nível molecular, e é isso que você tem para se parecer com algo mais real :): Provavelmente é bom investigar o box2d para ver sua solução para a dinâmica baseada em impulsos.
Teodron #
@TravisG, como você resolveu o problema? Estou olhando para um problema semelhante ao tentar implementar um mecanismo de física muito simples.
cheesus diz para de disparar mods
1
@cheeesus Já faz um tempo desde que eu trabalhei nele, mas acredito que usei mais iterações com timesteps menores.
TravisG

Respostas:

5

Uma solução que encontrei ao usar a correção de posição é ter algumas iterações e variar a força a cada iteração.

doPhysics();

int num_iterations = 5;
for(int iteration=0; iteration<num_iterations; ++iteration)
{
    float strength = float(iteration+1)/num_iterations;
    correctPositions(strength);
}

Portanto, a primeira iteração tem uma força de 1 / num_iterations e a última tem uma força de 1. Isso torna minhas simulações mais suaves e mais estáveis ​​do que simplesmente usar o mesmo número de iterações com uma força fixa.

DaleyPaley
fonte
2
Solução agradável, mas por que funciona?
Gustavo Maciel
5

Seu problema está no fato de você não ter um estado de "repouso" para seus corpos. Qualquer sistema de física tem uma quantidade de energia, seja ela cinética, térmica e assim por diante. Na realidade, objetos sólidos se deformam levemente e transformam energia cinética em calor, embora dificilmente seja mensurável. Também vale a pena notar que, na realidade, não existe um objeto completamente sólido. Mesmo materiais densos, como o diamante, têm espaço entre os átomos, dando à estrutura atômica espaço para flexionar e absorver energia cinética.

Para tornar isso relevante, os corpos em repouso estão em um estado em que as únicas forças em vigor são a "força normal", ou seja, a força que impede os corpos de flutuar entre si. A magnitude dessa força normal é proporcional à densidade dos objetos e a que distância eles penetraram um no outro.

Os mecanismos de física chamam esse valor de "slop".

Aqui está o truque: calcule a inclinação, corrija a posição dos corpos e aplique a força normal, com base na velocidade relativa dos dois corpos. durante a atualização dos próprios corpos, calcule a energia cinética de cada corpo. Se estiver abaixo de um valor mínimo, coloque o corpo em repouso, até que uma força de magnitude suficiente seja aplicada a ele. (geralmente o dobro do valor mínimo).

Ian Young
fonte
0

Por que não adicionar uma superfície "pegajosa" a eles e fazê-los ficar em uma posição de repouso gradualmente e quando outro objeto o atinge, ele transfere alguma energia para ele, fazendo com que ele se mova, mas a superfície pegajosa fará com que ele perca parte dessa energia e pare em uma posição de descanso. parece que o gif não tem atrito.

anon
fonte