[javascript] Disegnare sistema solare con Three.js e WebGL

Three.js è una fantastica libreria javascript per il rendering interattivo in 2D e 3D su HTML5. Qualche giorno fa mi sono trovato a voler riprodurre dei fittizi sistemi stellari ed ho deciso di riportare di seguito un esempio semplificato per chiunque volesse provare da se. Il risultato che vogliamo ottenere è il seguente (zoom con rotellina del mouse, tasto sinistro per ruotare, tasto destro per spostare):


      

Già che c’ero ho inserito anche un paio di esempi per confronto con sistemi stellari realistici: in particolare il nostro sistema solare con i suoi otto pianeti principali in proporzione, una seconda versione con i pianeti ingranditi, ma proporzionati sempre al Sole ed infine il sistema Glise 581 sempre in proporzione corretta.

Inutile dire che si tratti di una semplificazione estrema (le orbite sono circolari, anziché essere ellittiche, e giacciono tutte sul medesimo piano), ma è sufficiente a darci un’idea della vastità dello spazio. 🙂

Detto questo mettiamoci all’opera.

Anzitutto procuriamoci Three.js e, già che ci siamo, jQuery (non è indispensabile, ma mi divertirò ad unirli insieme).

Adesso creiamo il contenuto della nostra pagina index.htm

Creiamo anche un file main.css per il foglio di stile ed uno main.js per il codice javascript. 

Colleghiamo le librerie jQuery, three.min.jsOrbitControls.jsthree.interaction.js.

Infine inseriamo un div che farà da contenitore per il nostro rendering. 

Potremmo usare anche un canvas, ma Three.js ci permette di aggiungere un rendering anche al comune DOM in HTML.

Fatto tutto questo sistemiamo velocemente il CSS inserendo il seguente codice:

Inutile dire che ci potremmo divertire a personalizzarlo nei modi più disparati, ma per il momento è quanto ci basta per creare un riquadro nero di 800px di lato.

Fatto tutto questo possiamo cominciare a lavorare sullo script. Definiamo anzitutto il minimo indispensabile:

In questo modo abbiamo definito la camera, la scena (è dove aggiungeremo tutti gli oggetti), il renderer che produrrà l’elemento DOM da aggiungere al suddetto div, i controlli che ci permetteranno di muovere la telecamera rispetto alla scena e il sistema di interazione (per sviluppi futuri).

Per far funzionare il tutto creiamo una funzione chiamata init(), il nome è comunque a piacere, che lanciamo all’inizio, ed una funzione animate() che richiamiamo subito dopo.

Grazie a requestAnimationFrame( animate ) animiamo tutto il sistema. Dopo approfondiremo.

Intanto cominciamo disegnando un singolo corpo nello spazio (banalmente una sfera).

Per poter gestire l’oggetto appena creato aggiungiamolo al vettore pianeti che dichiariamo come variabile globale.

Per aggiungere un grosso oggetto al centro ci sarà sufficiente quindi usare, dentro la funzione init() alla riga evidenziata:

Gli oggetto saranno aggiunti su un piano cartesiano tridimensionale, di coordinate x, y e z. La posizione (0,0,0) è quindi all’origine degli assi del piano cartesiano. La telecamera punta direttamente verso questo origine ad una distanza sull’asse z di 10.

Proviamo ad aggiungere una seconda sfera con:

A questo punto vogliamo aggiungere anche il cerchio dell’orbita, che appunto non è altro che una circonferenza (nel nostro caso semplificato eh!):

La nostra funzione accetta come argomento il raggio dell’orbita, che sarà disegnata centrata in (0,0,0).

La circonferenza è composta di 64 segmenti che collegano altrettanti vertici. Creiamo quindi la geometria nella qual inseriamo le coordinate dei vertici, il tutto sarà poi riempito con il materiale di tipo LineBasicMaterial.

Integriamo la funzione in quella per creare i singoli pianeti, utilizzando un argomento apposito per poter decidere se aggiungerla o meno.

Con Math.sqrt(x*x + y*y) calcoliamo il raggio per ciascuna orbita, ossia la distanza del corpo sul piano xy rispetto all’origine degli assi.

Adesso proviamo ad aggiungere i seguenti pianeti:

Dovremmo poter vedere un sistema statico, simile a quello dell’esempio.

Adesso cominciamo ad animarlo, preparando anzitutto la funzione che farà ruotare i pianeti. Per farlo ruotare utilizziamo delle coordinate polari, dove ci sarà sufficiente aumentare l’angolo theta.

La funzione ruota accetta un oggetto m e un valore per la “massa”, che ci permetterà di fare variazioni sulla velocità globale del sistema. Dal momento che la velocità dei pianeti varia con l’inverso della distanza, secondo la seguente formula:

v_{o}\approx {\sqrt {{\frac {GM}{r}}}}

Possiamo approssimare il moto angolare con una variazione di theta come segue:

Quindi applichiamo il movimento per ogni singolo corpo creando una specifica funzione:

In questo modo facciamo due cose. Con:

Facciamo ruotare i corpi attorno a se stessi (rotazione).

Con:

Li facciamo ruotare attorno alla stella (rivoluzione).

Aggiorniamo infine la funzione animate():

Infine aggiungiamo lo sfondo stellato generando dei punti casuali nello spazio tutto intorno con:

Ed impostiamo la telecamera di base:

In questo modo posizioniamo la telecamere con l’inquadratura leggermente inclinata e di lato rispetto al sistema.

L’intero script che utilizziamo è il seguente:

Se abbiamo fatto tutto bene otterremo il risultato di sopra.

Rispondi

This site uses Akismet to reduce spam. Learn how your comment data is processed.