ROBOTICA

video
immagini
papers
progettati
costruiti
toolbox
vrml
simulatori

links

 

Papers
meccanica
sistemi
documents

Capitolo 9° Creare oggetti di diversa forma : il nodo IndexedFaceSet e IndexedLineSet Capitolo 11°

Finora abbiamo considerato geometrie molto semplici. In particolare abbiamo visto negli esempi l'uso delle primitive sfera, cono e cilindro. Un'altra primitiva molto semplice e utile è la Box, che definisce un parallelepipedo. Ne vedremo un uso nell'esempio incluso in questo paragrafo.

Anche se con queste semplici primitive si possono realizzare dei mondi interessanti, mondi più complessi si basano spesso su geometrie più complicate. Nella maggior parte dei casi, quando ci troviamo nella situazione di dover modellizzare un oggetto del mondo reale è difficile poterlo fare con semplici sfere, cilindri, parallelepipedi e coni. L'ideale in questi casi sarebbe quello di poter definire i poligoni che costituiscono l'oggetto che si vuole porre nella scena.

Ovvio che, una tale operazione, se fatta a mano, può essere molto laboriosa e complicata ; basti considerare che oggetti non molto complicati possono arrivare anche a migliaia di poligoni. In tali casi l'uso di un tool di sviluppo opportuno risulta necessario. In pratica si realizza il modello in un pacchetto grafico esterno e poi si converte il file in formato vrml (esistono convertitori per i formati più conosciuti come DXF o 3DS).
Se invece, tutto ciò di cui abbiamo bisogno è un semplice oggetto come una piramide allora si può procedere anche ad editing diretto dei singoli poligoni senza eccessivo sforzo.

Vediamo dunque come questo sia possibile con un semplice esempio. Supponiamo di voler creare una casa ; o quanto meno un modello molto semplificato. Al massimo della semplificazione, possiamo pensare ad una casa come ad un cubo con sopra una piramide (tralasciamo porte e finestre ; non costerebbe comunque molto considerarle).
Valgono ancora gli stessi discorsi fatti per l'esempio della freccia. Il tetto deve appoggiare sul cubo sottostante, per cui dovrò considerare questo legame nello sviluppo del mondo. Il seguente listato indica come realizzare questo semplice oggetto ; si noti che il sorgente non è molto diverso dall'esempio visto nel paragrafo precedente ; cambia solo la geometria dei singoli pezzi.

#VRML V2.0 utf8
#semplice casetta : uso del nodo IndexedFaceSet
Transform { translation 0 0 -100 #pongo la casa ad una certa distanza #dall'osservatore rotation 0 1 0 .5 # ruoto leggermente per dare una migliore #vista iniziale children [ Shape { appearance Appearance { material Material { emissiveColor .5 .5 .5 } # come colore della base uso un grigio chiaro } geometry Box { size 20 20 20 } } Transform { translation 0 10 0
children [ Shape { appearance Appearance { material Material { emissiveColor .8 0 0 } } geometry IndexedFaceSet { coord Coordinate { point [ -10 0 10, 10 0 10, 10 0 -10, -10 0 -10, 0 10 0 ] } coordIndex [ 0, 3, 2, 1, -1 0, 1, 4, -1 1, 2, 4, -1 2, 3, 4, -1 3, 0, 4, -1
] } } ] } ] }

Casetta

Come si può vedere il numero di parentesi da chiudere cresce molto in fretta.
Il risultato di questo listato si può vedere nella figura riportata (mondo realizzato con Live3d 2.0).

Effettivamente il lavoro da effettuare quando si vuole creare un oggetto dandone i poligoni risulta essere piuttosto lungo. E' appunto per questo che, per oggetti più complessi si ricorre di solito a pacchetti grafici esterni.

Analizziamo ora il listato sopra riportato. In questo esempio ho usato una primitiva che ancora non avevamo visto : Box. Quello che fa è molto semplice : crea una scatola di dimensioni pari a quelle specificate nel campo size. Il field size necessita di 3 valori ; essi sono la dimensione lungo x, quella lungo y e quella lungo z. Si noti che l'oggetto (come accade anche pe cilindro e sfera) viene posto in modo tale da avere il baricentro nell'origine dell'attuale sistema di riferimento.

Una volta definita la base passiamo a creare il tetto. Dato che il tetto appoggia sulla base e che se si sposta la base il tetto la deve seguire, conviene strutturare questo collegamento innestando il nodo Transform della piramide nel campo children del primo Transform. In questo modo siamo sempre sicuri che il tetto andrà sempre a posizionarsi sopra il cubo (ripeto ancora una volta che finchè faremo mondi statici questi benefici non saranno evidenti).
Fatto questo, resta da definire quale sia la forma da dare al tetto. Abbiamo deciso per una forma a piramide. Non esistendo una primitiva 'piramide' dobbiamo definire l'oggetto specificandone i poligoni.
A tal fine, nel campo geometry indico allora il nodo IndexedFaceSet. Questo nodo contiene due fields: il campo coord e il campo coordIndex. Il campo coord specifica i punti che costituiscono i vertici dei poligoni che formano l'oggetto. Si possono indicare questi vertici in qualsiasi ordine. In base alla posizione che occupano nella lista, questi punti possono essere individuati da un numero. Il primo vertice sarà il vertice 0, il secondo sarà il vertice 1 e così via.
In particolare il campo coord contiene il nodo Coordinate il cui field point contiene i punti sottoforma di triplette di coordinate. Notate bene che le coordinate sono fornite pensando di definire la piramide in modo cha abbia centro nell'origine del sistema di riferimento. La traslazione sopra il cubo non è di competenza del field geometry, bensì del nodo Transform ; se tenessi qui conto della traslazione sopra il cubo, avrei una doppia traslazione (e soprattutto non potrei riusare la piramide in altre parti).
Definiti i vertici, si deve procedere ad indicare quali sono le facce che costituiscono l'oggetto. Per rappresentare una faccia si indicano i vertici che la compongono. Questo viene fatto nel field coordIndex. In questo campo indico i numeri dei vertici che compongono la faccia. Per indicare che non vi sono altri vertici e che voglio chiudere la definizione di una faccia riporto il numero -1.
L'ordine con cui riporto i vertici non è casuale ; ed è anzi molto importante. I vertici di una faccia vanno riportati in modo tale che una faccia visibile abbia i vertici listati in senso antiorario. Se si sbaglia l'orientamento la faccia non verrà visualizzata (verrà visualizzata la faccia interna invece). Questo meccanismo consente al browser di non doversi preoccupare delle facce non visibili e quindi di non dover procedere al loro rendering, velocizzando la resa della scena.

Direi che abbiamo detto abbastanza sul nodo IndexedFaceSet.

Diamo ora una veloce occhiata al nodo IndexedLineSet. Questo nodo consente di creare delle spezzate 3D.Basterà specificare i punti da raggiungere e quali punti connettere tra di loro. Vediamo il seguente frammento di file vrml :

geometry IndexedLineSet {
	coord Coordinate {
	   point [  0 0 0, 0 10 0, 10 10 0, 10 0 0 ]
	}
coordIndex [ 0 1 2 3 -1 ] }

In questo caso, unendo le spezzate creo un semplice quadrato (si badi bene NON un poligono quadrato: ci si vede attraverso). La spezzata congiunge i punti nell'ordine fornito.