Em um mecanismo de física 2D, como evito resoluções de colisão inúteis quando os objetos param?

9

Em um mecanismo de física que estou desenvolvendo (para aprender) usando o love-2d , implementei resoluções de colisão desta maneira:

FixedUpdate(dt)  // I use fixed timestep
 foreach collide c1 in allNotStaticColliders
   c1.integartePhysic // i.e. apply gravitational force..
   foreach collider c2 "near" c1 // "near"= I use spatial hashing 
      if collide(c1,c2)
        resolve collision (c1,c2)  // the heavy operation
        collison callbacks c1
        collison callbacks c2
        ...

animação de objetos caindo e parando

Como você pode ver no final da animação gif, há uma deterioração do FPS quando todos os colisores estão quase aterrados sobre um objeto estático.

o estado estático final, com 2 FPS

Isso ocorre porque o número de resoluções de colisão aumenta à medida que os objetos passam mais tempo tocando enquanto se acomodam. No entanto, muitos dos cálculos são "inúteis" porque os objetos já se estabeleceram em posições estáveis ​​um contra o outro.

Qual é a melhor prática (espero que não exija um diploma de física) para evitar essas detecções de colisão "inúteis"?

Editar: dicas DMGregory aceitas e chegar a esse resultado (ainda não é o ideal)

insira a descrição da imagem aqui

(Vermelho = estático, Azul = ativo, Verde = em suspensão)

dnk drone.vs.drones
fonte
11
A abordagem usual é "adormecer" objetos que parem, e não considerar as interações entre objetos adormecidos / estáticos (mas um objeto adormecido ainda pode ser despertado por uma interação de um objeto dinâmico que ainda está acordado e em movimento). Infelizmente, isso só ajuda quando um objeto está totalmente em repouso. Se estou lendo seu exemplo corretamente, parece que seus problemas de desempenho começam quando os objetos ainda estão se acomodando e se movendo um pouco. Tudo o que posso pensar em fazer aqui é adicionar mais atrito / amortecimento ao sistema (possivelmente com um limiar de velocidade), para que pequenos movimentos decaiam para um verdadeiro descanso mais rápido.
DMGregory
@DMGregory Isso soa como uma boa resposta. Adicioná-lo?
Anko

Respostas:

9

Eu suspeitava que o OP já conhecia essa abordagem, por isso mencionei em um comentário apenas como ponto de partida, mas vou tentar aprofundar um pouco mais ...

A maioria dos mecanismos de física divide objetos dinâmicos em dois grupos: " acordado " e " adormecido ".

Os objetos dormem quando estão em repouso e acordam quando são movidos ou acelerados por alguma influência externa.

Um objeto adormecido se comporta como um objeto estático na maioria dos aspectos - seu movimento não é integrado ao longo do tempo (porque está em repouso, por isso não tem movimento) e o mecanismo ignora colisões entre objetos que estão adormecidos ou estáticos.

Um objeto adormecido sentado em um piso estático não passa por ele, apesar da falta de resposta de colisão, porque toda a integração do movimento é ignorada para objetos adormecidos, incluindo a gravidade.

Portanto, apenas colisões envolvendo pelo menos um objeto dinâmico acordado precisam ser verificadas:

Collisions    Static          Sleeping           Awake
          ------------------------------------------------
Awake     |    Check        Check & Wake         Check
Sleeping  |     No               No
Static    |     No

Isso pode reduzir drasticamente o número de objetos que precisam de simulação ativa, especialmente em pilhas que, como ilustrado na pergunta, têm muitas colisões mútuas para verificar pouco ou nenhum movimento líquido.

Dormir só ajuda uma vez que os objetos realmente chegar a descansar no entanto, que pode demorar um pouco.

Algumas coisas que você pode fazer para descansar mais cedo:

  • Tenha uma velocidade ou momento mínimo diferente de zero e fixe qualquer coisa que fique abaixo dele para zero. (Este é basicamente um epsilon, comumente usado na comparação de carros alegóricos)

  • Use fricção, amortecimento e colisões inelásticas para retirar a energia do sistema e ajudá-lo a descansar mais rapidamente no geral.

  • Aumente o atrito / amortecimento / inelasticidade seletivamente para objetos em movimento lento para dar-lhes aquele empurrão final para descansar, sem afetar o comportamento de corpos mais energéticos.

DMGregory
fonte
Boa resposta. Você aponta várias idéias boas. Para as verificações de sono / vigília, vejo dois pontos fracos: 1) se o objeto adormecido o1 sob o objeto adormecido o2 acorda se afastando do o2, ele não acorda o2; 2) se eu remover uma plataforma estática sob um objeto de dormir, esse objeto não desperta (sob força gravitacional)
dnk drone.vs.drones
11
@ dnkdrone.vs.drones Boas observações. Como nunca escrevi um mecanismo de física, não tenho certeza de como isso é tratado normalmente. Uma possibilidade é que, ao definir um objeto para suspensão, armazenamos uma lista de objetos em que ele está tocando (ou o adicionamos a um cluster local de objetos). Quando ativamos um objeto adormecido, também ativamos tudo em sua lista / cluster. Pode haver opções mais elegantes, como procurar contatos próximos no momento em que você acorda (antes que ele se afaste).
DMGregory