Come faccio a correggere gli oggetti "scoppiare" o jitter nel motore fisico?


11

Ho un semplice motore fisico che risolve le collisioni semplicemente correggendo direttamente la posizione dei corpi sovrapposti (solo cerchi per ora), invece di cambiare semplicemente la velocità o applicare un impulso. La velocità viene modificata solo dopo che gli impatti sono già stati risolti o durante la parte di integrazione.

Ho avuto il problema che negli ammassi di oggetti gli oggetti superiori applicano troppa pressione (questo esiste implicitamente, non c'è modellizzazione della pressione nell'algoritmo) sugli oggetti nella parte inferiore dell'heap, il che si traduce nella loro spinta attraverso i piani, eccetera.

Volevo risolvere questo problema ordinando gli oggetti in base alla loro coordinata y, quindi le collisioni vengono risolte dal basso verso l'alto. Ma ora, il motore mostra uno strano comportamento di scoppio per oggetti che dovrebbero effettivamente essere a riposo (vedi GIF)

inserisci qui la descrizione dell'immagine

Senza solo darti il ​​codice sorgente - cosa potrebbe essere?


5
Tutto sommato, questo è simile alla risoluzione di un sistema lineare di equazioni in modo iterativo (o sistema non lineare, a seconda dei vincoli / condizioni / ecc.). In entrambi i casi, stai vedendo questi artefatti perché sono numericamente la cosa corretta da vedere: stati intermedi di un processo convergente. Evitare questo è piuttosto difficile e potrebbe implicare un sacco di attacchi cattivi (comunque, questo accade nella vita reale, a livello molecolare, ed è quello che hai lì per assomigliare meglio a qualcosa nella vita reale :)). Probabilmente è utile indagare box2d per vedere la loro soluzione per la dinamica basata sugli impulsi.
teodron,

@TravisG come hai risolto il problema? Sto osservando un problema simile quando provo a implementare un motore fisico molto semplice.
Cheesus dice di smettere di sparare mod

1
@cheeesus È da un po 'che non ci lavoro, ma credo di aver usato solo più iterazioni con timestep più piccoli.
TravisG,

Risposte:


5

Una soluzione che ho trovato usando la correzione della posizione è quella di avere alcune iterazioni e variare la forza ad ogni iterazione.

doPhysics();

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

Quindi la prima iterazione ha una forza di 1 / num_iterations e l'ultima ha una forza di 1. Questo rende le mie simulazioni più fluide e più stabili del semplice utilizzo dello stesso numero di iterazioni con una forza fissa.


2
Bella soluzione, ma perché funziona?
Gustavo Maciel,

5

Il tuo problema sta nel fatto che non hai uno stato "a riposo" per i tuoi corpi. Qualsiasi sistema fisico ha una quantità di energia, sia quella cinetica, termica e così via. In realtà, l'oggetto solido si deforma leggermente e trasforma una certa energia cinetica in calore, sebbene difficilmente misurabile. Vale anche la pena notare che in realtà non esiste un oggetto completamente solido. Anche materiali densi, come il diamante, hanno spazio tra gli atomi, dando spazio alla struttura atomica per flettersi e assorbire energia cinetica.

Per rendere ciò rilevante, i corpi a riposo sono in uno stato in cui le uniche forze in effetti sono la "forza normale", vale a dire, la forza che impedisce ai corpi di fluttuare l'uno nell'altro. L'entità di quella forza normale è proporzionale alla densità degli oggetti e fino a che punto si sono penetrati l'un l'altro.

I motori fisici chiamano questo valore "slop".

Ecco il trucco: calcola la pendenza, correggi la posizione dei corpi e applica la forza normale, in base alla velocità relativa dei due corpi. durante l'aggiornamento dei corpi stessi, calcolare l'energia cinetica di ciascun corpo. Se è al di sotto di un valore minimo, metti il ​​corpo a dormire, fino a quando non viene applicata una forza di magnitudine sufficiente. (di solito il doppio del valore minimo).


0

Perché non aggiungere una superficie "appiccicosa" a loro e farli aderire gradualmente a una posizione di riposo e quando un altro oggetto lo colpisce, trasferisce un po 'di energia in esso facendolo muovere ma la superficie appiccicosa gli fa perdere parte di questa energia e si ferma in posizione di riposo. la gif sembra non avere attriti.

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.