Mappe 3D e loro applicazioni
Genera mappe 3D da qualsiasi parte del mondo … a cosa serve?
Beh, oltre ad essere visivamente impressionante, può essere utile in alcuni campi come l’architettura, le applicazioni di monitoraggio e video giochi.
In effetti, quest’ultima è la ragione principale del modulo (addon) che ho creato in Godot 3.0.
Come funziona
Per prima cosa ho deciso di utilizzare ciò che rende disponibile MapBox: immagini satellitari e mappe altimetriche.
L’API è facile da usare e devi solo creare un account e ottenere il token.
Il processo di generazione delle mappe utilizza la heightmap per disegnare il modello 3D e un’immagine satellitare della stessa area per il colore di ciascun poligono disegnato.
Presto intenzione di aggiungere texture e normali (che consentirebbero di aumentare il livello di dettaglio o di ridurre il numero di poligoni senza perdere qualità), anche se possibile, LOD automatico
Mappe di elevazione
Le mappe di elevazione utilizzano immagini le cui informazioni di elevazione sono codificate nei loro colori:
Ogni componente di colore (rosso, verde e blu) corrisponde a una quantità (in metri). E che, secondo la documentazione ufficiale, viene decodificato con questa formula:
var altitude = -10000 + ((r * 256 * 256 + g * 256 + b) * 0,1)
Quindi è interessante notare che le mappe di elevazione non sono una falsa colorazione che indica l’elevazione.
Per questo motivo, la forma dell’oggetto non può essere sempre compresa dall’immagine di elevazione.
Nella mia implementazione ogni pixel corrisponde a un quadruplo, o 2 triangoli che prendono come elevazione il pixel analizzato e i suoi pixel contigui, in questo modo:
var bottomleft = Vector3 (i * dist - half_size, ht * altitude_multiplier, j * dist - half_size) var bl_color = ht[i][j]["color"] var upperleft = Vector3 (i * dist - half_size, ht * altitude_multiplier, (j + 1) * dist - half_size) var ul_color = bl_color.linear_interpolate (ht, 0.5) var upperright = Vector3 ((i + 1) * dist - half_size, ht * altitude_multiplier, (j + 1) * dist - half_size) var ur_color = bl_color.linear_interpolate (ht, 0.5) var bottomright = Vector3 ((i + 1) * dist - half_size, ht * altitude_multiplier, (j) * dist - half_size) var br_color = bl_color.linear_interpolate (ht, 0.5) surf_tool.add_color (bl_color) surf_tool.add_vertex (bottomleft) surf_tool.add_color (br_color) surf_tool.add_vertex (bottom right) surf_tool.add_color (ul_color) surf_tool.add_vertex (upperleft) surf_tool.add_color (br_color) surf_tool.add_vertex (bottom right) surf_tool.add_color (ur_color) surf_tool.add_vertex (upperright) surf_tool.add_color (ul_color) surf_tool.add_vertex (upperleft)
È interessante notare che al momento del rendering i colori non sono esattamente uguali alla trama, ciò dovuto all’interpolazione dei colori, aspetto che migliorerò nelle prossime versioni.
Immagine satellitare (trama)
L’immagine satellite, o texture, è usata per dare un colore per ogni triangolo disegnato in 3D.
Quindi il vertice che viene aggiunto prende il colore del pixel corrispondente.
Ottieni i dati da MapBox
Un altro elemento importante di questa implementazione è il servizio che MapBox mette a disposizione (sinceramente, ho cercato tra i dati resi disponibili dalla NASA, ma non ho trovato una risposta rapida, e ho deciso di seguire la via più semplice, visto che mi è familiare con le API MapBox).
Semplicemente decodificando le coordinate nella tessera corrispondente, si ottengono le immagini in elevazione e satellitari. Ho approfittato di questa esigenza (per decodificare latitudine, longitudine e zoom nella tessera corrispondente), per creare una piccola libreria che mi consenta questa e altre decodifiche.
Risultato finale e problemi tecnici
Bene, come si dice sempre, un’immagine dice più di mille parole, quindi qui puoi vedere il risultato finale.
Va notato che a causa di problemi irrisolti, ciascuna immagine risulta nel rendering di 4 o 16 tessere o mesh, più piccola, che determina il disallineamento, in alcuni casi, delle tessere adiacenti, come si può vedere nel animazione.