In precedenza ho implementato cubi / tetraedri per rendere un IsoSurface. Ha funzionato ( YouTube ), ma la performance è stata terribile in quanto non ho mai avuto l'implementazione del livello di dettaglio variabile in base alla distanza di visualizzazione (o addirittura alla rimozione di blocchi vecchi e distanti).
Ho deciso di provare un'altra volta e farlo correttamente questa volta. Ho iniziato creando un OctreeNode che funziona come segue quando Build()
viene chiamato.
- Se il pezzo è troppo piccolo per essere costruito, ritorna immediatamente.
- Risolvi se la superficie passa attraverso il volume di questo pezzo.
- In tal caso, quindi decidere se vogliamo aumentare il LOD (perché la fotocamera è vicina)
- In tal caso, genera 8 bambini e chiama lo stesso processo su di essi
- In caso contrario, creare la mesh utilizzando le dimensioni del nodo corrente
Alcuni PseudoCode:
OctNode Build() {
if(this.ChunkSize < minChunkSize) {
return null;
}
densityRange = densitySource¹.GetDensityRange(this.bounds);
if(densityRange.min < surface < densityRange.max) {
if(loDProvider.DesiredLod(bounds)² > currentLoD) {
for(i 1 to 8) {
if(children[i] == null) {
children[i] = new OctNode(...)
}
children[i] = children[i].Build();
}
} else {
BuildMesh();
}
return this;
}
}
¹ Oltre a restituire la densità in un punto, la sorgente di densità può determinare la possibile gamma di densità per un dato volume.
² Il provider LoD prende un riquadro di selezione e restituisce il LoD massimo desiderato in base alla posizione / frustum della telecamera, alle impostazioni dell'utente, ecc ...
Quindi ... Tutto funziona abbastanza bene. Utilizzando una sfera semplice come sorgente Densità e mostrando tutti i nodi:
E solo le foglie:
Tuttavia, ci sono un paio di problemi:
- Devo definire il volume iniziale di delimitazione (e più è grande, più elaborazione devo fare)
- Alla radice dell'albero, non ho idea di quanto saranno profonde le foglie, quindi la mia numerazione LoD inizia con la qualità più bassa (radice) e aumenta man mano che i blocchi diventano più piccoli. Poiché LoD è ora relativo al volume iniziale, non è molto utile quando voglio fare cose con dimensioni / qualità specifiche.
Ho pensato a un paio di opzioni ma entrambi sembrano imperfetti:
- Mantieni una raccolta di Octrees e aggiungi / rimuovi in base alla distanza. Non riesco a vedere come fare a maglie bene¹, inoltre avrei bisogno di un elenco di nodi vuoti noti, soprattutto se desidero superfici 3D arbitrarie (per evitare di ricalcolare ripetutamente i volumi vuoti)
- Aggiungi un nodo padre alla radice corrente, quindi aggiungi sette fratelli per il nodo originale. Funzionerebbe e sarebbe on demand, ma sembra complesso ridursi sensibilmente mentre il giocatore si muove attraverso il paesaggio. Renderebbe anche i numeri LoD ancora meno significativi.
¹ [In chiarimento a Q sotto] Al momento, se 2 nodi fisicamente adiacenti nella struttura sono in LOD diversi, ho un po 'di codice per forzare i verbi in modo tale che non ci siano cuciture quando vengono generate le mesh. Sono in grado di farlo conoscendo la densità per più nodi circostanti. In uno scenario in cui ho 2 ocre indipendenti fianco a fianco, non avrei un modo semplice per recuperare queste informazioni, risultando in cuciture.
Qual è un modo ottimale per affrontare questo?