In un motore fisico 2D, come posso evitare inutili risoluzioni di collisione quando gli oggetti si fermano?


9

In un motore fisico che sto sviluppando (per l'apprendimento) usando love-2d , ho implementato risoluzioni di collisione in questo modo:

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
        ...

animazione di oggetti che cadono e si fermano

Come puoi vedere alla fine dell'animazione GIF, c'è un decadimento FPS quando tutti i collider sono quasi a terra su un oggetto statico.

lo stato statico finale, con 2 FPS

Questo perché il numero di risoluzioni di collisione aumenta man mano che gli oggetti trascorrono più tempo a toccarsi mentre si depositano. Tuttavia, molti dei calcoli sono "inutili" perché gli oggetti si sono già sistemati in posizioni stabili uno contro l'altro.

Qual è la migliore pratica (si spera che non richieda una laurea in fisica) per evitare questi "inutili" rilevamenti di collisioni?

Modifica: accetta suggerimenti DMGregory e arriva a questo risultato (non ancora ottimale)

inserisci qui la descrizione dell'immagine

(Rosso = statico, blu = attivo, verde = inattivo)


1
L'approccio usuale è quello di "dormire" gli oggetti che si fermano e non considerare le interazioni tra oggetti dormienti / statici (ma un oggetto dormiente può ancora essere svegliato da un'interazione da un oggetto dinamico che è ancora sveglio e in movimento). Purtroppo questo aiuta solo quando un oggetto è completamente a riposo. Se sto leggendo correttamente il tuo esempio, sembra che i tuoi problemi di prestazione inizino quando gli oggetti si stanno ancora sistemando e si muovono leggermente. Tutto quello che posso pensare di fare qui è aggiungere più attrito / smorzamento al sistema (possibilmente con una soglia di velocità) in modo che i piccoli movimenti decadano rapidamente fino al vero riposo.
DMGregory

@DMGregory Sembra una buona risposta. Aggiungerlo?
Anko,

Risposte:


9

Sospettavo che OP conoscesse già questo approccio, quindi l'ho menzionato in un commento solo come punto di partenza, ma proverò a svilupparlo un po 'di più ...

La maggior parte dei motori fisici divide gli oggetti dinamici in due gruppi, " sveglio " e " addormentato ".

Gli oggetti dormono quando siedono a riposo e si svegliano quando vengono spostati o accelerati da qualche influenza esterna.

Un oggetto dormiente si comporta come un oggetto statico sotto molti aspetti: il suo movimento non è integrato nel tempo (perché è a riposo, quindi non ha movimento) e il motore ignora le collisioni tra oggetti che sono dormienti o statici.

Un oggetto che dorme seduto su un pavimento statico non lo attraversa, nonostante la mancanza di una risposta alla collisione, perché tutta l'integrazione del movimento viene saltata per gli oggetti che dormono, inclusa la gravità.

Pertanto, è necessario verificare solo le collisioni che coinvolgono almeno un oggetto dinamico attivo:

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

Ciò può ridurre drasticamente il numero di oggetti che necessitano di una simulazione attiva, specialmente in pile che, come illustrato nella domanda, hanno molte collisioni reciproche per verificare movimenti netti piccoli o nulli.

Dormire aiuta solo quando gli oggetti raggiungono effettivamente il riposo, il che potrebbe richiedere del tempo.

Alcune cose che puoi fare per riposare prima:

  • Avere una velocità o un momento minimo diverso da zero e bloccare a zero tutto ciò che scende al di sotto di esso. (Questo è fondamentalmente un epsilon, comunemente usato per confrontare i galleggianti)

  • Usa attrito, smorzamento e collisioni anelastiche per assorbire energia dal sistema e aiutarla a raggiungere il riposo più velocemente in generale.

  • Aumenta selettivamente attrito / smorzamento / anelasticità per gli oggetti che si muovono lentamente per dare loro la spinta finale a riposare, senza influenzare il comportamento di corpi più energici.


Buona risposta. Fai notare un sacco di buone idee. Per i controlli sonno / veglia vedo 2 punti deboli: 1) se l'oggetto dormiente o1 sotto l'oggetto dormire o2 si sveglia allontanandosi da o2, non si sveglia o2; 2) se rimuovo una piattaforma statica sotto un oggetto dormiente, quell'oggetto non si sveglia (sotto la forza di gravità)
dnk drone.vs.drones

1
@ dnkdrone.vs.drones Buone osservazioni. Non avendo mai scritto un motore fisico da solo, non sono sicuro di come questo sia gestito normalmente. Una possibilità è che, quando si imposta un oggetto su sleep, memorizziamo un elenco di oggetti che sta toccando (o lo aggiungiamo a un cluster locale di oggetti). Quando svegliamo un oggetto che dorme, svegliamo anche tutto nel suo elenco / cluster. Potrebbero esserci opzioni più eleganti, come verificare la presenza di contatti vicini al momento del risveglio (prima che venga spostato).
DMGregory
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.