Sto scrivendo un motore fisico e ho difficoltà a trovare un buon modo per progettare l'archiviazione dei dati.Accesso alla memoria compatibile con la cache in fisica ristretta e loop di collisione
La funzionalità che voglio:
- avere una classe che rappresenta un PhysicsBody
- avere una classe che rappresenta un volume di collisione (diciamo una scatola)
- Ogni organismo fisica può avere un altro volumi di collisione collegati ad esso
- È possibile avere un corpo fisico senza volume di collisione
- Opzionale: CollisionVolume senza un corpo fisico. (pensa a Trigger Volumes)
In questo momento ho fondamentalmente due cicli. Uno che aggiorna i corpi fisici nella simulazione. Aggiorna la loro posizione/velocità/rotazione. Il secondo ciclo esegue il rilevamento delle collisioni su tutti i volumi di collisione. È solo un ciclo annidato per il controllo delle collisioni tra ogni coppia di volumi di collisione. (So che può essere fatto meglio ma questo è un argomento separato)
So che il modo ideale è quello di memorizzare gli oggetti in matrici contigue.
std::vector<PhysicsBody> m_bodies;
std::vector<CollisionVolume> m_colliders;
problemi che ho trovato con questo approccio:
- La sua difficile da mantenere PhysicsBody -> rapporto CollisionVolume. Ad esempio, se voglio rimuovere un CollisionVolume dal mio vettore, lo cambierò con l'ultimo e tornerò indietro. I dati vengono spostati e se ho memorizzato un indice su CollisionVolume in PhysicsBody, non è più valido.
- Ogni volta che distruggo un PhysicsBody, il distruttore controllerà se vi è un eventuale volume di collisione collegato e rimuoverlo in modo appropriato anche dal sistema Physics. Il problema è che un vettore produrrà copie interne e le distruggerà e quando ciò accadrà causerà il caos rimuovendo i volumi di collisione che non avrebbero dovuto essere rimossi.
- CollisionVolume è in realtà una classe base (non deve essere) e altre classi derivano da essa come scatole/sfere e cosa no. Potrei potenzialmente non usare l'ereditarietà e trovare qualche altro design complicato, ma questo è qualcosa da tenere a mente.
Ho cercato di trovare un modo intorno ad esso, ma ha finito per memorizzare i puntatori invece:
std::vector<PhysicsBody*> m_bodies;
std::vector<CollisionVolume*> m_colliders;
La soluzione migliore per la cache riducendo al minimo non trova che mi è venuta è stata sovraccarico new/delete e la conservazione di questi oggetti in un pool di memoria solo per il sistema fisico.
Esistono altre soluzioni migliori? Ovviamente le prestazioni sono fondamentali.
lei ha ragione. Intendevo la cache amichevole.Alla fine sarebbe bello avere questo multithread ma non mi vedo farlo presto. Fisserò il titolo! – Nixt
Non conosco il numero di elementi in anticipo, motivo per cui ho dovuto seguire il percorso vettoriale. Se dovessi immagazzinare oggetti nel vettore, i costi di trasferimento potrebbero essere costosi, ma le delocalizzazioni maggiori sarebbero poco frequenti. Un vettore garantisce che i dati sottostanti siano sempre in un blocco contiguo di memoria, quindi la località viene preservata. Ma non risolve gli altri problemi. – Nixt