![]() |
|
![]() |
||||
![]() |
ROBOTICA
video
immagini
papers
progettati
costruiti
toolbox
vrml
simulatori
![]() |
Creare oggetti di diversa forma : il nodo IndexedFaceSet e IndexedLineSet | ![]() |
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
] } } ] } ] }
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.