ROBOTICA

video
immagini
papers
progettati
costruiti
toolbox
vrml
simulatori

links

 

Papers
meccanica
sistemi
documents

Capitolo 23° Esempio di animazione Capitolo 25°

Consideriamo ora un altro esempio, leggermente più complesso dei precedenti, in modo tale da consolidare le nozioni acquisite nei precedenti paragrafi.

Supponiamo di volere realizzare una semplice stanza. La stanza è completamente vuota tranne che per un orologio. Anziché avere un orologio sempre fermo, supponiamo di volerlo dotare di lancette che segnano il trascorrere del tempo. In particolare colleghiamo lo scorrere delle lancette al tempo effettivo, in modo che rappresenti in maniera corretta l’ora corrente (se l’ora sul computer dell’utente è settata in maniera corretta ovviamente).

Metteremo una lancetta per i secondi, una per i minuti e una per le ore.

Questo è solo un pezzo del mondo. Una stanza dovrebbe contenere qualcosa d’altro ; ma noi ci concentriamo su questo oggetto, senz’altro il più complicato che abbiamo visto sino a questo punto.

Analizziamo bene la struttura delle lancette. Rappresentiamo le lancette con dei parallelepipedi molto stretti. Il problema è che queste lancette devono poter ruotare. Ma attenzione ! Non devono ruotare rispetto al loro centro. Una lancetta deve ruotare attorno all’estremo connesso al centro dell’orologio.

Il trucco che ho utilizzato in questi casi è quello di definire una sfera centrale a cui connetto rigidamente la lancetta. A questo punto posso ruotare la sfera centrale (attorno al suo centro) e la lancetta ruoterà con essa. Vi ricordate quando sottolineavo nei primi paragrafi l’importanza di strutturare le dipendenze tra oggetti ? Allora poteva sembrare un esercizio inutile. Ora, con le animazioni in gioco, strutturare in maniera corretta il mondo risulta determinante.

Questa operazione va ripetuta per tutte e tre le lancette. Non importa se le sfere si sovrappongono. Basta che questo non sia visibile dall’esterno.

Ovviamente le rotazioni da dare alle sfere saranno diverse, a seconda che siano collegate alla lancetta dei secondi, dei minuti o delle ore.

Avremo la necessità di definire tre sensori di tempo, ognuno con cicli diversi ; il sensore per i secondi avrà un ciclo di 60 secondi, dopo i quali la lancetta ricomincia a comportarsi nello stesso modo ; quello per i minuti avrà un ciclo di 60 minuti e quello per le ore di 12 ore (dubito comunque che il vostro utente resterà a vedere il completamento di questo ciclo).

Detto questo, la stesura del sorgente risulta ora abbastanza banale. Per rendere l’orologio un po’ più realistico metterò le lancette in modo che non si compenetrino nel loro spostamento (le pongo a z leggermente diverse, come un vero orologio del resto) e porrò almeno quattro stanghette per segnare le ore : 3 - 6 - 9 - 12.

Per aggiungere un po’ di luce alla stanza aggiungo una lampadina attaccata al soffitto che genera una luce tramite un nodo PointLight.

Ponete particolare attenzione al modo di strutturare il mondo e a come vengono ridiretti gli eventi.

#VRML V2.0 utf8
# semplice stanza con un orologio che segna il trascorrere
# del tempo

# setto la posizione iniziale Viewpoint { position 0 1.5 2 } # definisco ora le pareti della stanza. Per migliorare la #visibilita’ coloro le pareti in maniera diversa DEF appartamento Transform { children [ Shape { appearance Appearance { material Material { diffuseColor 1 0 0 } } geometry IndexedFaceSet { coord DEF mycoords Coordinate { point [-3 0 3, 3 0 3, 3 0 -3, -3 0 -3, -3 3 3, 3 3 3, 3 3 -3, -3 3 -3] } # pavimento e soffitto coordIndex [ 0 1 2 3 -1, 7 6 5 4 -1] } } Shape { appearance Appearance { material Material { diffuseColor .8 .8 .8 } } geometry IndexedFaceSet { # usando USE riuso il nodo Coordinate definito in precedenza... # le coordinate sono le stesse ! coord USE mycoords # definisco le 2 pareti laterali coordIndex [1 5 6 2 -1, 0 3 7 4 -1] } } Shape { appearance Appearance { material Material { diffuseColor .6 .6 .6 } } geometry IndexedFaceSet { coord USE mycoords # definisco le pareti davanti e dietro coordIndex [0 4 5 1 -1, 6 7 3 2 -1] } } ] } # creo ora una lampadina che scende dal soffitto e illumina la stanza. Transform { translation 0 2.7 0 children [ Shape { appearance Appearance { material Material { diffuseColor .3 .3 .3 } } # filo modellizzato come sottile cilindro geometry Cylinder { radius .005 height .6 } } # la lampadina e’ una sfera di colore giallo attaccata # all’estremita’ del filo Transform { translation 0 -.325 0 children [ Shape { appearance Appearance { material Material { diffuseColor .8 .8 0 } } geometry Sphere { radius .05 } } # qui definisco la luce che scaturisce dalla lampadina. PointLight { location 0 2.35 0 radius .1 } ] } ] } # creiamo ora l'orologio. # il posizionamento e' dato dal nodo Transform che lo include. # Lo posiziono sulla parete di fronte DEF clock Transform { translation 0 1.5 -2.98 # messo appoggiato sulla superficie della parete ad una altezza di 1.5 metri children [ Transform { rotation 1 0 0 1.57 children [ Shape { appearance Appearance { material Material { diffuseColor .3 .3 0 } } # ho usato un cilindro basso e ruotato in modo da avere la base # verso l’osservatore. Ho quindi ottenuto # la solita forma a cerchio degli orologi da muro. geometry Cylinder { radius .4 height .02 } } ] } # definisco ora i quattro segni per le ore principali (3-6-9-12) Transform { translation -.27 0 .021 children [ DEF segno Shape { appearance Appearance { material Material { diffuseColor 0 0 1 } } geometry Box { size .08 .04 .002 } } ] } Transform { translation .27 0 .011 children [ # anche qui riuso il nodo definito in precedenza... # le stanghette sono tutte uguali USE segno ] } Transform { translation 0 .27 .011 # due delle stanghette devono essere in verticale... # per cui ruoto la stanghetta che riuso, la quale # era definita in orizzontale rotation 0 0 1 1.57 children [ USE segno ] } Transform { translation 0 -.27 .011 rotation 0 0 1 1.57 children [ USE segno ] } #definisco ora le lancette #lancetta delle ore # sfera che funge da perno DEF perno_ore Transform { children [ Shape { appearance Appearance { material Material { diffuseColor 1 0 0 } } # molto piccola in modo che non sia visibile... # ma la funzione che svolge e’ a noi molto utile ! geometry Sphere { radius .005 } } # si noti come la lancetta e' figlia del perno. Transform { translation 0 .08 .02 children [ Shape { appearance Appearance { material Material { diffuseColor 0 0 1 } } geometry Box { size .06 .16 .002 } } ] } ] } # sfera che funge da perno per la lancetta dei minuti... # si va a sovrapporre al perno per i secondi... ma # in ogni caso non si vede per cui non ho problemi DEF perno_minuti Transform { children [ Shape { appearance Appearance { material Material { diffuseColor 1 0 0 } } geometry Sphere { radius .005 } } # la lancetta deve essere figlia del perno dei minuti Transform { translation 0 .11 .04 children [ Shape { appearance Appearance { material Material { diffuseColor 0 1 0 } } geometry Box { size .03 .22 .002 } } ] } ] } # lo stesso ripetuto per i secondi. DEF perno_secondi Transform { children [ Shape { appearance Appearance { material Material { diffuseColor 1 0 0 } } geometry Sphere { radius .005 } } # lancetta dei secondi Transform { translation 0 .11 .06 children [ Shape { appearance Appearance { material Material { diffuseColor 1 0 0 } } geometry Box { size .01 .22 .001 } } ] } ] } ] } # definisco ora i tre sensori di tempo DEF secondi TimeSensor { cycleInterval 60 enabled TRUE loop TRUE } DEF minuti TimeSensor { cycleInterval 3600 enabled TRUE loop TRUE } DEF ore TimeSensor { cycleInterval 86400 enabled TRUE loop TRUE } # definisco ora i 3 interpolatori... qui dovrebbe essere tutto chiaro. # Ruoto le sfere attorno all’asse z # le lancette che sono attaccate ad esse ruotano solidalmente. DEF rotsec OrientationInterpolator { key [0 .25 .5 .75 1] keyValue [0 0 1 0, 0 0 1 -1.57, 0 0 1 -3.14, 0 0 1 -4.71, 0 0 1 -6.28] } DEF rotmin OrientationInterpolator { key [0 .25 .5 .75 1] keyValue [0 0 1 0, 0 0 1 -1.57, 0 0 1 -3.14, 0 0 1 -4.71, 0 0 1 -6.28] } DEF rotore OrientationInterpolator { key [0 .25 .5 .75 1] keyValue [0 0 1 0, 0 0 1 -1.57, 0 0 1 -3.14, 0 0 1 -4.71, 0 0 1 -6.28] } # da ultimo indirizzo gli eventi in uscita in modo opportuno # il sensore di tempo dei secondi manda l’uscita # fraction_changed che va a settare la frazione # nell’interpolatore # l’interpolatore calcola di conseguenza il nuovo valore # di rotazione e lo usa per settare il campo rotation del # perno della lancetta dei secondi # lo stesso vale per le altre coppie di ROUTE ROUTE secondi.fraction_changed TO rotsec.set_fraction ROUTE rotsec.value_changed TO perno_secondi.set_rotation ROUTE minuti.fraction_changed TO rotmin.set_fraction ROUTE rotmin.value_changed TO perno_minuti.set_rotation ROUTE ore.fraction_changed TO rotore.set_fraction ROUTE rotore.value_changed TO perno_ore.set_rotation

Stanza con orologio

Per quanto riguarda l’ora rappresentata, essa è quella corrente in quanto gli intervalli di ciclo del nodo TimeSensor sono collegati con il clock dell’orologio.

L’esempio è un po’ più corposo rispetto agli altri. In ogni caso andrebbe sviluppato ancora molto in quanto tutto quello che abbiamo è una stanza vuota con una lampadina e un orologio che riporta fedelmente l’ora corrente. L’arredamento è tutto da inventare.

Con una dimensione di circa 5Kb siamo riusciti ad avere un risultato abbastanza interessante. Ammobiliando la stanza (magari anche con modelli presi da programmi di rendering esterni o da librerie disponibili in rete) potremmo rendere l’ambiente molto più accogliente e realistico.

Nel prossimo paragrafo vedremo come si può iniziare ad interagire con il mondo in maniera molto semplice tramite appositi sensori. Vedremo per esempio come aggiungere un semplice sensore che ci sonsentirà di accendere e spegnere la luce della lampadina nella stanza.