2009-09-23 12 views
10

Sto progettando il mio motore di sistema particellare, questo è per scopi di apprendimento, non voglio veramente usare un motore esistente.Particle System Design?

In questo momento ho generato particelle bellissime, ma voglio impaginare il motore per rendere più facile il lavoro con loro.

Ho riflettuto su una classe "Sistema di particelle",

quella classe conterrebbe i seguenti riferimenti:

particlesList: Un elenco delle particelle che compongono il sistema.

systemEmitter: L'emettitore sistema di particelle, la classe emettitore dovrebbe essere in grado di eseguire diverse tecniche di emissione di particelle, come per esempio, emettendo dalle linee, punti, emettendo caso da un poligono. Anche questa classe dovrebbe fare il controllo delle emissioni, come l'emissione verso un punto, lontano da un punto, in una direzione e tempo da emettere.

particleController: gestisce ad esempio la rotazione intorno ad un punto, granulometria variabile, colori particelle variabili, zone intorno al sistema di cui le particelle reagiscono in modi diversi, rilevamento di collisione (con altri oggetti o all'interno delle particelle se diventa necesary).

particelle renderer: preposto alla redazione questo sistema, i tipi di fusione variabili, texture di particelle, tipi di particelle, come triangoli, cerchi, su misura ...

Questo quattro voci, sarebbe comporre la classe sistema di particelle. Alcuni FX potrebbero richiedere più di un sistema di particelle, ad esempio un Fire FX, potrebbero utilizzare un sistema per l'incendio, un sistema per il fumo e un sistema per le scintille.

Questo è quello che ho in mente, ma mi piacerebbe davvero sapere se questo approccio progettuale è buono, o se vedi mi manca qualcosa o potrei/dovrei fare qualcosa di diverso. Non ho pensato ad un modo semplice per "salvare" FX, ad esempio quale sarebbe il modo migliore per dire al mio motore, "disegnare Fuoco", "disegnare esplosione", "disegnare fontana", ecc., Magari memorizzare informazioni FX nei file xml sarebbe una buona idea, ecc.

Le opinioni sono davvero benvenute, e come ho detto prima, voglio davvero costruire questo, invece di usare un altro motore, per motivi di apprendimento.

risposta

5

Questo setup dovrebbe andare bene. Quello che spero tu stia pensando è quali dati costituiranno una particella che sarà nella classe delle particelle. Ti consigliamo di avere solo gli elementi essenziali, quindi devi solo leggere/scrivere il meno possibile di memoria durante l'esecuzione del sistema.

Per quanto riguarda i dati guidati dovrebbe essere abbastanza semplice. Suggerirei un'opzione di formato xml e binario per il caricamento. così puoi modificare facilmente le cose durante lo sviluppo (e non avere uno strumento). Una volta che hai uno strumento o hai fatto un tweaking, converto l'xml in binario per il caricamento rapido.

Si consiglia inoltre una classe manager che gestisce la creazione e l'aggiornamento di questi sistemi particellari. Ciò consentirebbe anche a te un posto dove gestire altre funzionalità che ha a che fare con tutti i tuoi sistemi. Alcuni esempi di ciò sono la limitazione della quantità di sistemi o particelle di particelle che possono essere gestiti per ragioni di prestazioni o con un piano di collisione che tutti i sistemi dovrebbero prendere in considerazione.

Si dice che questo è per scopi di istruzione e in quanto riguarda queste cose sono piuttosto pignoli (ma importante se si deve usare questo in un gioco che è pesantemente particellare).

Suppongo che stia utilizzando un'API come DirectX o OpenGL per il rendering. A tale riguardo vorrei che tutti gli effetti delle particelle condividessero lo stesso pool di memoria per le informazioni sui vertici. Questo aiuta molto la velocità di rendering. Vorrei anche tenere traccia dei limiti dell'area interessata da un sistema di particelle da utilizzare con il frustum culling (AABB o Circle).

Una parte enorme dell'aggiornamento di un sistema di particelle è il modo in cui gli attributi passano da un valore a un altro. Quanto più dinamico è possibile fare l'interpolazione dei valori, tanto migliori saranno i tuoi effetti. La semplice interpolazione lineare potrebbe essere abbastanza buona, ma potrebbe essere meglio avere un grafico dinamico che viene usato per interpolare i valori. Ad esempio, invece di passare da 0 a 255 blu in un secondo, potrebbe essere interessante passare da 0 a 128 in 0,2 secondi, quindi 128-255 in 0,8 secondi. Aggiungendo ciò aumenterai notevolmente le opzioni su come appaiono i tuoi effetti.

Inoltre, penso che tu abbia una buona idea di cosa vuoi fare. La tua menzione del rendering di diversi tipi di particelle mi dice che stai pensando a questo nel modo giusto. Ho visto persone che costruiscono motori di particelle concentrandosi solo sul rendering di un quad billboard. Avere la possibilità di emettere la geometria 3d rende davvero le cose grandiose. Potresti anche voler pensare (se non lo hai già fatto) alla possibilità per il tuo sistema di prendere informazioni sul modello e dividerlo dinamicamente in particelle separate da emettere. In realtà, l'esplosione di un modello sembra molto migliore, quindi la visualizzazione di particelle esplosive e lo sbiadimento dell'oggetto o il passaggio a uno stato danneggiato.

+0

Grazie per la tua risposta !, sì, sto pensando di renderlo con OpenGL. Anche l'idea di interpolazione non lineare è veramente buona, e dovrebbe essere in grado di creare delle visuali piuttosto buone con essa. – Goles

1

Solo alcune idee per l'ottimizzazione di particelle sprite 2D semplici.

Una buona idea è quella di inviare tutte le particelle in un array di vertici/VBO e utilizzare un vertex shader per aggiornare le loro posizioni nel tempo. Questo è ottimo se si dispone di un movimento semplice che può essere facilmente descritto utilizzando una formula matematica dove x(t) e y(t) (cioè, dipendono solo in tempo).

Un'altra ottima idea è utilizzare sprite puntiformi invece di triangoli e quad. Ciò dovrebbe ridurre la larghezza di banda richiesta sulla pipeline a un quarto.


Nel mio spazio sim ho implementato l'approccio più banale: le particelle inviati come quad strutturato utilizzando glBegin()/glEnd(). Vengono scaricati nell'attuale "settore" come singoli oggetti e sono completamente indipendenti dal momento del dumping in poi. Questa è la cosa più primitiva, stupida e idiota da fare ed è responsabile di una grande riduzione delle prestazioni, specialmente dal momento che ciò che faccio è scorrere gli oggetti tramite l'iteratore del vettore STL e inviarli uno dopo l'altro in sequenza.

È necessario considerare quante particelle si desidera e che cosa si desidera che facciano. * Vuoi che reagiscano all'ambiente e si scontrino? Quindi è necessario un aggiornamento gestito su CPU e dati inviati più e più volte. * Vagano nel modo più stupido possibile? Quindi potresti riuscire a farla finita con l'invio di tutte le particelle come VBO e TBO e aggiornarle in shader.

Buon divertimento!


Aggiornato a relazionarsi con il commento # 1 dal richiedente :-)

Quello che vorrei fare è utilizzare il KISS principle.Ciò significa: una classe denominata ParticleEmitter contenente un array di vertici, una matrice di velocità e un codice STL vector con istanze di collettori semplici quali piano, sfera, triangolo. Inoltre, disponi di un "globale" * STL vector con collisori. Quindi aggiorna le velocità in base ai collisori.

Simile può essere fatto con gli affettori (gravità, vento e così via): un altro vettore STL in ParticleEmitter con gli agenti e un altro STL "globale" vector con gli agenti.

Gli agenti di ricerca e i collettori sarebbero classi che implementerebbero affectParticle(particle_t*). dove struct particle_t { float x,y,z; float vx,vy,vz; }. Lo terrei una struttura POD ed eseguirò l'aggiornamento in ParticleEmitter::update().

Tuttavia, se si esegue questa operazione su iPhone, potrebbe essere una complicazione? Forse puoi farcela con ciò che hai già implementato? Non ho idea di come il mio design possa influenzare i risultati dei benchmark, ma mi sembra abbastanza ragionevole se si tiene conto del conteggio delle particelle, del collisore e dell'affector, perché sembra che potrebbe scalare con circa n*c+n*a.

Questi sono solo i miei pensieri ad-hoc e il modo in cui l'ho implementato personalmente. Il tuo design, o il design di altre persone, sarebbe probabilmente migliore :-)

* "Globale" tra virgolette, perché probabilmente avrebbe senso utilizzare qualsiasi partizione di spazio che hai in uso.

+0

Ciao Ivan, grazie per la risposta, in questo momento sto sviluppando questo sistema su iPhone, ho fatto buoni progressi, da quando ho raggiunto il traguardo sul rendering di 3.000 16x16 pixel GL_POINT_SPRITES, utilizzando VBO e raggiungendo tra 45-55 fps. Penso che sia abbastanza decente. Tuttavia ora voglio iniziare a lavorare su come le particelle possono interagire e scontrarsi con altri oggetti, ho pensato in qualche modo, ma mi piacerebbe davvero sentire alcune idee a riguardo. Grazie ancora. – Goles

1

Ho implementato lo stesso buon design per il mio motore in C++. Non ho usato riferimenti e criteri modello (strategie - leggi "Modern C++ Desing" di Alexandresku). Il polimorfismo statico offre prestazioni migliori.

0

Vorrei fare alcuni commenti in base alla mia esperienza.

  1. Tradizionalmente, la maggior parte delle particelle utilizza AOS (Array of Struct) per memorizzare gli attributi delle particelle. Ma questa potrebbe non essere la decisione migliore. L'uso della rappresentazione SOA (Struct of Array) ti darà molta flessibilità nell'aggiungere attributi di ciascun sistema di particelle. Inoltre, sarà molto più semplice migliorare le prestazioni con SIMD con SOA. Ad esempio, facendo 4 particelle insieme usando le istruzioni SSE.
  2. posizione di dove la particella emette è solo l'inizializzazione di un attributo di particella. Quando si emettono particelle, è probabilmente necessario inizializzare altri attributi, come durata, velocità, ecc. È possibile astrarre tutte queste funzioni come inizializzatori. Per la posizione, potresti avere un inizializzatore del disco, un inizializzatore di box, ecc.
  3. Alcuni moderni sistemi di particelle adottano il concetto di evento. Il sistema di particelle può generare un evento (ad esempio pioggia che collide con il terreno) e un altro sistema di particelle può ascoltare ed eseguire qualche azione (ad esempio, emettere schizzi).

A proposito, penso che il modo migliore sia studiare la progettazione di applicazioni/middleware esistenti e anche la sperimentazione.