Grafico della scena come contenitore di oggetti?


8

Il grafico della scena contiene nodi di gioco che rappresentano oggetti di gioco. A prima vista, potrebbe sembrare pratico usare Scene Graph come contenitore fisico per oggetti di gioco, ad esempio std :: vector <>.

La mia domanda è: è pratico usare Scene Graph per contenere gli oggetti di gioco o dovrebbe essere usato solo per definire collegamenti di oggetti / nodi di scena, mantenendo gli oggetti memorizzati in un contenitore separato, come std :: vector <>?


Qualcuno ha un'idea? Ho intenzione di utilizzare sia Scene Graph per organizzare gli attori / nodi di gioco, sia Vector per eseguire vari ordinamenti che dovrebbero essere più veloci dell'ordinamento di un albero SceneGraph a più vie.
Bunkai.Satori

@ Tutto: ho un'altra domanda: SceneGraph contiene l'intera mappa o dovrebbe contenere solo una parte della mappa, ad esempio la sua area visibile? Ovviamente, il grafico della scena sarebbe quindi continuamente aggiornato, mentre il giocatore si sposta sulla mappa.
Bunkai.Satori,

Risposte:


5

Decidere su quale tipo di gestione delle scene usare dipende molto dal tipo di logica che si sta tentando di eseguire. Considera i diversi consumatori della tua scena:

Consumatore di rendering

Il renderer probabilmente vuole solo sapere cosa è attualmente visibile all'utente in un dato punto. Vuole una gerarchia di volumi limite per l'abbattimento rapido ( articolo wiki BVH) in modo che possa capire che non è necessario disegnare una sedia all'interno di una barca perché i limiti della barca sono al di fuori del frustum della vista. Questo potrebbe essere incorporato in un ottetto .

Potrebbe anche voler avere l'idea che la sedia sia appoggiata sul retro all'interno della barca e che la barca stia rotolando su e giù su alcune onde quando finalmente viene vista. In questo modo, per trovare le coordinate mondiali finali dei vertici della sedia, può concatenare le trasformazioni della sedia e della barca e farcela (questo semplifica anche il tuo lavoro di programmatore).

Un altro modo di considerare questo problema è che il renderer sta probabilmente eseguendo una buona carta e alla fine vuole solo un mucchio di triangoli ordinati in modo da ridurre al minimo la trama, lo shader, il materiale, l'illuminazione e trasformare i cambiamenti di stato. Quest'ultimo probabilmente ti aiuterà più di un BVH, in termini di preformance.

Consumatore della logica di gioco

La logica del gioco probabilmente vuole solo un elenco semplice di cose che possono dialogare tra loro tramite un sistema di messaggistica, quindi probabilmente uno std :: vector va bene.

Il gioco potrebbe anche desiderare un modo per tenere traccia di chi è il più vicino a ciò, quindi una sorta di informazione [del vicino più vicino] [3] potrebbe essere utile in quel caso. Questo può essere fornito anche da un BVH, ma dover su e giù per il grafico potrebbe essere fastidioso.

Il gioco potrebbe anche voler sapere che quando sposta A, anche l'oggetto B di A dovrebbe spostarsi ... nel qual caso torniamo a una sorta di gerarchia di trasformazione.

Consumatore di fisica

La fisica del tuo gioco potrebbe voler avere una [rappresentazione speciale] [4] di spazi interni per un rilevamento delle collisioni molto veloce. In alternativa, potrebbe usare una sorta di ottetto o [hashing spaziale] [5] per trovare in modo efficiente cose che potrebbero scontrarsi.

Nessuna delle strutture di dati di fisica sopra sembra davvero un "grafico di scena" in senso Java3D.

Consumatore audio

Un motore audio vuole solo geometria, forse un insieme potenzialmente visibile (udibile) o una sorta di gerarchia del volume limite per calcolare l'attenuazione del suono e la propagazione. Ancora una volta, non è proprio un normale tipo di grafico di scena, anche se potrebbe benissimo essere un grafico di geometria nella tua scena.

In definitiva ... ... dipende solo dalle esatte esigenze della tua applicazione. Suggerirei di utilizzare un elenco semplice per iniziare e vedere dove sorgono i tuoi problemi. Potresti anche provare un elenco semplice con una gerarchia di trasformazione, perché questo è forse l'unico tipo di scenario utile per ragioni diverse dall'efficienza.

In bocca al lupo!


@ChrisE: +1 per una domanda eccellente. A mio avviso, questa è la risposta migliore qui, quindi lasciatemi contrassegnare questa come risposta accettata . Se ho capito bene, hai dimostrato che Scene Graph non è sempre la soluzione definitiva. Soprattutto in Game Logic, vedi un grafico di scena come il modo corretto di aggiornare la trasformazione (scala, traduzione) di oggetti correlati? Esempio, una sedia è sulla barca, quindi le coordinate della sedia vengono aggiornate mentre la barca si muove? In alternativa, vedi qualche soluzione migliore per l'aggiornamento delle coordinate relative?
Bunkai.Satori,

@ChrisE: Oltre a quanto sopra menzionato, nel caso in cui venga utilizzato Scene Graph, può essere esso stesso utilizzato come unico contenitore di oggetti per la scena o consiglieresti di avere un altro contenitore (diciamo std :: vector <>) oltre a Scene Grafico?
Bunkai.Satori,

2
In realtà stavo proprio suggerendo questo. Proverei a mantenere una gerarchia di trasformazione (qui, un albero n-ary in cui i nodi hanno un genitore e più figli e nessun figlio è condiviso tra i nodi) con ciascun nodo contenente un riferimento all'oggetto di gioco. Gli oggetti di gioco sono tenuti in un array separato e piatto (diciamo, std :: vector).
ChrisE,

Durante l'aggiornamento, puoi cercare l'elenco piatto ed eseguire la logica di gioco, e ogni volta che si verifica un movimento relativo (diciamo, la sedia viene spinta in avanti sulla barca) puoi usare la gerarchia di trasformazione per trovare la trasformazione finale da locale a mondo camminando i genitori del tuo oggetto e concatenando le loro trasformazioni. Questo utilizza la gerarchia di trasformazione per ciò che è meglio (semplificando il movimento relativo) e consente comunque di mantenere un comodo elenco di oggetti in giro.
ChrisE,

Un ulteriore miglioramento è quello di mantenere in ogni oggetto una bandiera sporca e una trasformazione di tutto al di sopra di esso nella gerarchia di trasformazione. La trasformazione da padre a mondo memorizzata nella cache (quella trasformazione che ho appena accennato) significa che per qualsiasi aggiornamento della posizione di un oggetto devi fare solo una moltiplicazione di matrice (la trasformazione relativa in padre con la trasformazione da padre a mondo). Ogni volta che aggiorni la relativa trasformazione, aggiorni anche la tua bandiera sporca.
ChrisE,

3

C'è una buona ragione per non usare il grafico della scena come contenitore per gli oggetti di gioco, e questo è istanziare. Se si desidera riutilizzare alcune risorse, ha molto più senso fare riferimento alla risorsa dal grafico della scena più volte che avere diverse copie effettive.


@Jari: +1 per una buona risposta. A quanto ho capito, l'approccio generale è avere un contenitore separato di mesh renderizzabili. Il grafico della scena si riferisce normalmente al contenitore di mesh renderizzabili, per acquisire informazioni sulla forma dell'oggetto. Oltre a ciò, ogni nodo del grafico della scena contiene informazioni sulla trasformazione. Jari, avendo un tale design, vorrei sapere, se è ancora raccomandato di avere un contenitore std :: vector <> separato per i nodi di gioco, diciamo per scopi di ordinamento più veloce o per altri motivi ..
Bunkai.Satori

2
Dipende: può essere utile avere in realtà diversi elenchi lineari di nodi per un'elaborazione più veloce di AI, fisica, qualunque cosa. Ma ci andrei dopo vedo se c'è un problema altrimenti.
Jari Komppa,

Quindi, per concludere, dovrebbe essere accettabile che all'inizio abbia un solo SceneGraph, che contenga tutti gli oggetti nella scena. Potete avvisare, per favore, se nel grafico della scena dovrebbero essere presenti anche telecamere, luci, grilletti?
Bunkai.Satori,

Tutto ciò che è interessato dalla gerarchia di trasformazione deve essere nel grafico della scena, ma non darei comunque al grafico della scena la proprietà, ma li memorizzerei altrove per un'elaborazione più semplice (animazione, fisica, ecc.).
Jari Komppa,

Capito Jari. Grazie. Inizierò con una versione più piccola e aggiungerò altri contenitori per una più facile elaborazione in seguito, se necessario.
Bunkai.Satori,

2

Separare il modello di oggetti e il modello di visualizzazione (il tuo scenario) di solito è una buona idea.

Vedi questo articolo sull'argomento.

Tra le altre cose, ciò consentirà l'uso di pool di oggetti. Che potrebbe essere essenziale per una gestione efficiente della memoria.


+1 per un buon contributo. Ho esaminato l'articolo. Discute gli schemi di programmazione e, se avessi capito correttamente, Object Model manterrebbe l'elenco degli oggetti nella scena organizzato in una specie di contenitore std: vector <>, mentre ViewModel conterrebbe gli stessi oggetti organizzati nel grafico della scena? Tuttavia, solo gli oggetti attualmente visualizzati sarebbero contenuti nel Grafico scena?
Bunkai.Satori,

E che dire di telecamere, grilletti, luci? faranno parte anche del grafico della scena?
Bunkai.Satori,

@ Bunkai.Satori Bene, potreste potenzialmente avere cose nello scenario che non sono visualizzate sullo schermo. Costruisci il tuo scenegraph, quindi potresti eseguire un algoritmo di abbattimento sullo scenegraph prima di eseguire il rendering dei nodi visibili. Le luci e i grilletti delle telecamere potrebbero esistere sia nel modello che nel modello di visualizzazione.
Nailer

Grazie per la risposta. Come hai menzionato l' abbattimento , come si fa in pratica? l'intera scena è inclusa nel grafico della scena o c'è solo la parte visibile? Se l'intera scena è nel Grafico scena, l'intero grafico scena viene attraversato per fotogramma per inviare solo l'area visibile nell'API OpenGL / DirectX? Dubito che l' intera scena venga inviata all'API in base al fotogramma, poiché la parte visibile di solito è inferiore al 5% rispetto alla scena completa. In alternativa, il grafico della scena è organizzato in qualche modo, per recuperare rapidamente le aree più vicine senza travelrsal completo per fotogramma?
Bunkai.Satori,

Metti tutta la tua scena nello scenario. Bilancia il grafico in base a un determinato criterio (ad es. Potresti ricavarne un oc-albero). Attraversare l'albero e determinare quali nodi sono "Visibile", "Parzialmente visibile" e "Invisibile" in base al fatto che le finestre di delimitazione siano nella vista frustum. È possibile creare un "grafico di visibilità" ultraleggero che sostanzialmente consiste solo di riferimenti a nodi SG e un flag. Dopo l'abbattimento del frustum puoi attraversare di nuovo l'albero per fare l'abbattimento dell'occlusione. Ripeti la selezione di ogni fotogramma o di ogni fotogramma in cui la fotocamera o la scena sono state contrassegnate come "sporche".
Nailer
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.