MokaByte Numero 18 - Aprile 1998
Foto
Tool di creazione vrml
di
Esempio mediamente complesso di programmazione Java-Vrml: tool interattivo per la creazione di ambienti vrml



Introduzione

 Nell'articolo del mese di marzo ci siamo soffermati su un esempio di programmazione Java-Vrml abbastanza complesso: la creazione di un oggetto di forma umana in vrml e relativo controllo (animazioni inlcuse).

Proseguiamo ora con un altro esempio di applicazione java-vrml non banale. L'intento è quello di fornire una idea delle potenzialità offerte dall'uso combinato di Java e vrml (e spero che a questo punto del corso ciò sia abbastanza chiaro a tutti i lettori che mi hanno seguito). Inoltre rappresenta un'ottima occasione sia per rivedere concetti visti nei mesi scorsi, sia per affrontare nuovi aspetti tralasciati in precedenza.

L'esempio analizzato in questo articolo riguarda la creazione di una applet Java in grado di consentire all'utente la generazione di semplici ambienti vrml: in pratica una sorta di tool visuale.
Ovviamente quello che si otterrà alla fine non potrà essere paragonato con i vari strumenti di authoring vrml presenti in circolazione: questo non è l'intento che si vuole conseguire. Tant'è che in questa prima versione dell'applicazione non è neppure prevista la possibilità di salvare gli ambienti creati. Questa limitazione è senz'altro pesante ed è connessa alle varie restrizioni imposte dai browsers html nella gestione dei files. Nel prossimo articolo mi riprometto di analizzare meglio la questione, cercando di trovare una soluzione.

Quale potrebbe essere allora l'utilità di una tale applicazione? Questa domanda ha senso soprattutto in considerazione del fatto che non riusciremo certo ad ottenere un tool comparabile ai vari strumenti di authoring già presenti.

L'aspetto veramente interessante è fornito dal fatto che la creazione del mondo avviene on-line. Tralasciando il fatto che la Telecom sarebbe senz'altro contenta se tutti noi creassimo mondi vrml on-line, va notato il fatto che in questo modo si aprono scenari decisamente interessanti.
Potremmo infatti pensare ad ambienti vrml modificati e costruiti da più persone. Ogni utente fornisce il proprio apporto specifico, aggiungendo qualche pezzo al mondo vrml. I navigatori che accedono al mondo successivamente alla modifica vedranno l'ambiente modificato e potranno a loro volta effettuare aggiunte.
Un'altra applicazione potrebbe essere rappresentata dalla collaborazione tra più utenti connessi allo stesso mondo per la creazione di un certo oggetto. La cooperazione on-line rappresenta uno dei settori della realtà virtuale di maggiore interesse e sul quale si incentrano diverse attività di ricerca.

Alla conclusione di questo articolo certamente non sarete in grado di realizzare applicazioni di questo tipo (o quantomeno non lo sarete se vi affidate solo a quanto in questo articolo è raccontato ;) ).
Come sempre, è però meglio iniziare da qualche parte. Questo articolo fornirà quindi le basi per costruirsi un proprio semplice tool di creazione di mondi vrml, dove per semplice intendo che verrà data la possibilità di creare banali oggetti (coni, sfere, cilindri, box), di spostarli e ruotarli nell'ambiente e di modificare il loro colore. Il tutto in modo visuale e interattivo.

Cosa manca? Moltissimo! In primo luogo manca la possibilità di rendere persistenti le modifiche (e con questo potremmo realizzare il mondo costruito da più persone cui accennavo prima).
Per quanto riguarda invece la creazione di ambienti nei quali gli utenti possono collaborare alla creazione di oggetti/prototipi, manca ancora molto: in particolare si devono toccare vari argomenti legati al networking, necessari per consentire a più utenti di condividere gli stessi ambienti. Per quanto riguarda quest'ultimo argomento, che rientra nella sfera degli ambienti virtuali condivisi, sto valutando l'opportunità di uno o più articoli futuri che trattino l'argomento. Presso il gruppo VRML DREAMERS (http://www.lucia.it/vrml) stiamo realizzando un progetto di questo tipo e un prototipo funzionante è già presente presso il sito http://multidream.logicom.it. Si tratta del primo ambiente in multi-utenza vrml on-line presente in Italia. Vi invito a farci un salto: sul sito troverete anche un po' di documentazione sull'argomento. Per chi fosse interessato a provarlo, periodicamente il gruppo organizza delle 'assemblee' virtuali che solitamente vengono comunicate sul newsgroup it.comp.lang.vrml. Chiusa parentesi.

Torniamo ora all'argomento di questo articolo: semplice tool visuale per la creazione di ambienti vrml.
 

Specifiche del tool

 Come dicevo in precedenza il tool sarà molto semplice. In particolare l'utente potrà creare oggetti dei seguenti tipi:

Come noterete si tratta delle primitive automaticamente previste dalle specifiche vrml 2.0 (e vrml97). Questa scelta è dovuta essenzialmente a ragioni di semplicità: come vedremo nel corso del progetto, sarebbe comunque stato banale introdurre altri oggetti, come per esempio una piramide.

Gli oggetti aggiunti devono poter essere posizionati all'interno dell'ambiente. A tal fine si è optato di concedere all'utente la possibilità di effettuare operazioni di drag and drop. In pratica basterà trascinare l'oggetto nella posizione desiderata. (In realtà vi sono delle problematiche non banali per raggiungere questo obiettivo, ma le vedremo al momento opportuno).

L'applet deve inoltre concedere la possbilità di ruotare e scalare gli oggetti introdotti.

Deve essere possibile riselezionare un oggetto preesistente in modo da modificarne le caratteristiche.

Infine, si deve concedere all'utente la possibilità di modificare il colore associato ad un oggetto.

Come potete notare le specifiche imposte al progetto sono abbastanza semplici. La relativa implementazione richiede però di superare problematiche di una certa difficoltà, legate soprattutto alle operazioni di drag and drop.

Si procede ora ad analizzare le diverse parti di cui si compone l'applicazione.
 

Layout dell'applet

 Partiamo dall'aspetto più semplice; probabilmente il meno importante. E' comunque utile rendersi subito conto di come dovrà apparire l'applicazione finale.

La figura seguente mostra il layout dell'applet.

Layout dell'applet

Nella parte destra dell'applet si trova una casella di scelta per la selezione degli oggetti da aggiungere. Il pulsante Add consente di aggiungere di fatto l'oggetto selezionato al mondo vrml.
Sempre in altro, si trovano tre barre di scorrimento che consentono di modificare le componenti R (rosso) G (verde) B (blu) del colore da assegnare ad un oggetto.
I sei pulsanti di rotazione consentono di ruotare l'oggetto selezionato lungo i 3 assi principali. I sei pulsanti di scale consentono di scalarlo. Gli step di rotazione e di scala possono essere specificati attraverso i campi di input posti in basso.
I pulsanti 'Up' e 'Down' sono necessari per completare le operazioni di spostamento degli oggetti. Infatti una traslazione mediante drag & drop con il mouse può coprire al massimo due dei tre gradi di libertà necessari. Si è scelto di sfruttare i movimenti del mouse per posizionare gli oggetti su un piano x,z (ricordo che l'asse z è perpendicolare allo schermo). Per modificare il piano x,z su cui muoversi (in pratica per alzare o abbassare l'oggetto) si deve agire con i pulsanti 'Up' e 'Down'.

Cosa manca? Mancano almeno due pulsanti:


Aggiungere oggetti a run-time

 L'aggiunta di oggetti a run-time è già stata analizzata nella quarta lezione di questo corso. In quell'articolo abbiamo visto come sia possibile creare dinamicamente dei nodi vrml e aggiungerli alla scena. A questo punto viene dunque data per scontata la conoscenza di questo argomento.

Partendo da un mondo vrml vuoto (o quasi, poi vedremo cosa dovrà essere presente in partenza), l'utente può aggiungere dinamicamente semplici oggetti. Si dovrà dunque invocare il metodo createVrmlFromString passando come parametri delle stringhe opportune. La costruzione delle stringhe dipende dalla particolare geometria selezionata (box, cono, cilindro o sfera).

Sugli oggetti aggiunti devono essere possibili diverse operazioni, in particolare: traslazione, rotazione, cambio di colore, cambio di scala. Risulta dunque necessario acquisire le references ai campi che controllano questi parametri.
Tutte queste operazioni vanno ovviamente effettuate per qualunque oggetto presente nella scena.

A questo punto è necessario analizzare in dettaglio la tecnica utilizzata per effettuare le operazioni di drag and drop, in quanto da essa dipendono molte delle operazioni da effettuare per aggiungere un oggetto.
 

Traslazione degli oggetti

 Per traslare un oggetto abbiamo scelto la via più complicata: sarebbe stato certamente molto più semplice introdurre altri quattro bottoni in grado di controllare gli spostamenti lungo x e z. Abbiamo deciso di utilizzare il mouse in quanto il risultato finale offre certamente una maggiore comodità e rapidità di azione: dovremo però pagare in termini di complessità.

Per monitorare il movimento del mouse a pulsante premuto, sfruttiamo un nodo vrml visto un paio di lezioni fa: il nodo PlaneSensor.

Tale nodo è in grado di emettere la variazione di posizione del mouse su un piano x,y (a pulsante premuto sopra l'oggetto cui il sensore è associato). Dato che vogliamo controllare la posizione dell'oggetto su un piano x,z (per alzare/abbassare usiamo i pulsanti Up e Down) rimappiamo le traslazioni su x,y in traslazioni su x,z (la componente y viene mappata sulla z).

Cliccando sull'oggetto e trascinando verso l'alto si ottiene dunque l'effetto di allontanare l'oggetto.

Nasce subito una subdola complicazione.

Seguitemi per bene in questo punto: quando associamo un PlaneSensor ad un oggetto, piazziamo un piano invisibile che 'attraversa' l'oggetto. Il piano, senza trasformazioni esterne, è definito normale all'asse z.
Supponiamo ora che l'utente prema sull'oggetto (il sensore inizia quindi ad emettere eventi) e trascini il mouse verso l'alto. Le traslazioni positive lungo y vengono rimappate in traslazioni negative su z: l'oggetto, correttamente, si allontana. Fin qui tutto bene. Ma a questo punto l'utente decide di ruotare attorno all'oggetto e si pone alle sue spalle (sta ora guardando nella direzione positiva delle z). Una traslazione positiva sulle y in uscita dal sensore DEVE rimapparsi in una traslazione POSITIVA (e non più negativa) delle z: per coerenza l'oggetto dovrà allontanarsi e non avvicinarsi! In pratica l'uscita del sensore è in entrambi i casi identica (in quanto in entrambi i casi ho fatto un drag verso l'alto), ma l'uscita deve essere diversa (devo sempre allontanare l'oggetto dall'utente).

Per risolvere questa situazione introduco nell'ambiente un sensore di prossimità. Questo sensore non è ancora stato analizzato. Il suo funzionamento è molto semplice: rileva gli spostamenti dell'utente all'interno del mondo.

Per esempio:

 

DEF sensore ProximitySensor {

  center 0 0 0

  size 1000 1000 1000

}
 

Questo breve sorgente vrml definisce un sensore di prossimità centrato nell'origine e in grado di monitorare tutto il volume di una Box di lato 1000 (con buona approssimazione tutto il mondo vrml se l'utente non esce mai al di fuori di questo volume).

Il sensore emette due eventi molto interessanti:

In realtà emette anche altri eventi, ma per il momento ci bastano questi.

L'evento translation_changed è di tipo SFVec3f e contiene la nuova posizione dell'utente. Ad ogni spostamento dell'utente il sensore emette un nuovo valore riportante la sua posizione in coordinate assolute.

L'evento orientation_changed è di tipo SFRotation e contiene il nuovo orientamento dell'utente. Ad ogni cambio di orientamento si genera un evento di questo tipo.

A questo punto è chiaro a cosa possa servirci un tale nodo. All'interno dell'applet ci mettiamo in ascolto degli eventi translation_changed in uscita dal sensore. Per ogni evento arrivato aggiorniamo un paio di variabili interne che fungono da immagine della posizione attuale dell'utente. Quando sopraggiunge un evento dal PlaneSensor (e quindi è in atto una operazione di drag sull'oggetto), si verifica la posizione dell'utente rispetto all'oggetto; in base ad essa si potrà dunque decidere come rimappare le y sulle z (se cioè renderle negative oppure conservarle positive).

Primo problema risolto... e anche senza eccessiva fatica.

Problema numero 2: supponiamo ora di camminare attorno all'oggetto sino a quanto ci troviamo ad osservarlo ad un angolo di 90 gradi rispetto alla posizione iniziale (lo stiamo guardando di lato). Se pensiamo ancora al nostro piano invisibile su cui agisce il PlaneSensor, scoprirete che adesso vi sta passando attraverso. Il sensore opera sull'oggetto, quindi quando cliccate il mouse sopra l'oggetto e fate un drag qualcosa in uscita lo otterrete senz'altro. Il problema qui è che a piccolissime variazioni lungo x, corrispondono ENORMI variazioni in uscita dal PlaneSensor (questo perchè l'angolo tra voi e il piano è molto piccolo, tendente a zero: rifletteteci un attimo e capirete il motivo di questo problema: la prima volta che mi capitava restavo allibito davanti ad un oggetto che alla minima traslazione veniva catapultato a migliaia di metri di distanza!!!).

Il problema non è di così semplice soluzione come il precedente. O almeno questa soluzione semplice io non l'ho ancora trovata: per cui vi sottopongo quella che sono riuscito a mettere insieme dopo qualche notte insonne ;) .

Sarebbe moooolto bello che il piano ruotasse assieme all'osservatore. Fare cioè in modo che esso risulti sempre normale rispetto alla congiungente utente-oggetto. In questo modo avremmo risolto i problemi relativi alle traslazioni lungo x.

Esiste un nodo Vrml che fa decisamente al caso nostro: Billboard.
Consente infatti di ruotare automaticamente l'oggetto presente all'interno del suo campo children in modo da presentarsi sempre di fronte all'osservatore. Il suo orientamento dipende dunque dalla posizione che l'utente assume all'interno del mondo.

Per esempio:

 

Billboard {

  axisOfRotation 0 1 0

  children [

    Shape {

      appearance Appearance {

        material Material { diffuseColor 1 0 0 }

      }

      geometry Box { size 10 10 10 }

    }

  ]

}
 

In questo modo avrete una Box sempre rivolta verso l'utente. L'osservatore vedrà sempre la faccia frontale e non potrà mai vederne gli spigoli laterali. L'asse attorno al quale ruotare viene specificato dal campo axisOfRotation: 0 1 0 indica l'asse y.

Inserendo il nodo PlaneSensor all'interno di un campo children di un nodo Billboard il gioco è fatto. Il piano relativo al PlaneSensor ruoterà assieme all'utente e sarà sempre perpendicolare alla congiungente osservatore-oggetto.

Fatto questo nasce però un secondo problema: non possiamo più associare il PlaneSensor all'oggetto da traslare. Perchè? semplice! Dato che l'oggetto da associare al PlaneSensor deve essere presente all'interno dello stesso campo children cui il sensore appartiene, si avrebbe un effetto Billboard anche sull'oggetto introdotto. Il risultato è semplice da immaginare, con l'oggetto stesso che ruota in funzione della posizione dell'osservatore, e con l'utente di fronte al monitor a domandarsi del perchè il programmatore abbia introdotto dei pulsanti di rotazione, visto che poi l'oggetto si mette a ruotare da solo!

La soluzione che ho scelto di seguire è la seguente:
non fare il drag direttamente sull'oggetto, ma su un apposito cursore ad esso associato. Sarà il cursore ad essere inserito nel campo children del nodo Billboard e sarà dunque lui a ruotare in funzione degli spostamenti dell'utente. L'oggetto aggiunto sarà al di fuori del nodo Billboard e quindi se ne resterà tranquillamente fermo.

Spero che a questo punto non vi siate persi. Comunque, sappiate che abbiamo finito: l'operazione di drag and drop adesso funziona che è una meraviglia ;).

Per concludere questa parte, riporto il codice vrml che deve essere presente nel mondo vrml 'vuoto', quello cioè presente prima di iniziare a costruire.

 
 
 

#VRML V2.0 utf8
 
 

Viewpoint {

  position 7 2 8

  orientation 0 1 0 .5

  description "inizio"

}
 
 

NavigationInfo {

        headlight FALSE

        avatarSize [.5 2.0 .5]

}
 
 

DirectionalLight{

        direction -.5 -1 .2

        intensity 1

}
 
 

DirectionalLight {

        direction 0 0 -1

        intensity .5

}
 
 

DEF sensore ProximitySensor {

        center 0 0 0

        size 1000 1000 1000

        enabled TRUE

}
 
 

DEF Root Group {

  children [
 
 

    DEF Cursor Transform {

      children [

        DEF Bill Transform {

          children [

            Shape {

              appearance Appearance {

                material Material { diffuseColor 0 0 1 }

              }

              geometry Box { size 3 .2 .2 }

            }

            Shape {

              appearance Appearance {

                material Material { diffuseColor 0 0 1 }

              }

              geometry Box { size .2 .2 3 }

            }

          ]

        }

        DEF Sens PlaneSensor {}

      ]

    }
 
 

  ]

}
 
 
 

Tralasciamo i nodi relativi a luci e punti di vista.
Come visto in precedenza, inseriamo un sensore di prossimità che sottopone a controllo il volume nel quale l'utente può muoversi.

La parte più interessante riguarda il nodo Root.
Questo nodo è destinato ad ospitare tutti i nodi creati a run-time e contenenti i vari oggetti aggiunti dall'utente. Ogni oggetto che verrà creato verrà aggiunto come figlio diretto di questo nodo. Si badi dunque che si trova ad un livello gerarchico superiore rispetto al nodo Billboard.

Il nodo Root contiene anche un nodo predefinito di nome Cursor. Tale nodo definisce il cursore da associare all'oggetto attivo in un certo istante (quello su cui si ripercuotono le varie operazioni di scala, rotazione, cambio colore, ecc.).
Come si può notare il nodo Cursor incapsula un nodo Billboard, il quale a sua volta contiene la descrizione fisica del cursore (un paio di Box messe in croce) e il PlaneSensor ad esso associato.
Il nodo Transform che avvolge il nodo Billboard è necessario per poter traslare il cursore da un oggetto ad un altro in conseguenza della selezione da parte dell'utente di un certo oggetto.

Concludendo, rimane appunto da analizzare quest'ultimo aspetto: la possibilità cioè di riselezionare un oggetto aggiunto precedentemente in modo da modificare alcuni dei suoi parametri.
L'oggetto selezionato correntemente viene evidenziato dal cursore. Per selezionare un altro oggetto basta cliccarci sopra: in conseguenza di questo fatto il cursore si sposta sull'oggetto selezionato. Sarà dunque indispensabile associare un sensore di tocco quando si procede ad aggiungere a run-time i nodi vrml che costituiscono le varie entità di cui si compone la scena.
 

Costruzione dell'applet Java

 Analizziamo ora molto velocemente l'applet Java che consente di controllare il tutto.

L'applet si compone di due classi:

La prima classe gestisce le operazioni di inizializzazione del layout e di gestione degli eventi AWT.

In occasione della creazione di una nuova entità (box, sfera, cono o cilindro), si istanzia un oggetto dell'altra classe. Quindi in un certo momento saranno attivi un oggetto della classe Builder e tanti oggetti della classe Oggetto.

La classe Oggetto incapsula al suo interno tutti i dati relativi ad un particolare oggetto introdotto (con il nome della classe uguale ad 'Oggetto' qui le ripetizioni si sprecano: sorry, ma l'importante è che alla fine si capisca qualcosa ;) ). Oltre ai dati specifici di ogni entità aggiunta, la classe esporta una serie di metodi che consentono di traslare, ruotare, scalare e cambiare di colore ad un certo oggetto.

Tutte le problematiche principali legate all'applicazione sono state analizzate nel paragrafo precedente. Tralasciamo ora il codice relativo alla classe Builder: è molto banale e di fatto non fa altro che recepire gli eventi AWT, instanziare oggetti della classe Oggetto quando serve e invocare gli opportuni metodi per modificare alcune caratteristiche dell'entità selezionata.

Unico aspetto da notare è rappresentato dalla modalità di acquisizione della reference al browser vrml. E' meglio abbandonare la tecnica che ho seguito sino a questo momento nel corso (sfruttare cioè le classi di Netscape). Sul sito della Silicon Graphics e sulle FAQ EAI è consigliato utilizzare la seguente forma:
browser = Browser.getBrowser(this);
Questo dovrebbe conferire anche maggiore portabilità alle vostre applet EAI.
Sino ad ora avevo seguito l'approccio alternativo in quanto era quello utilizzato all'interno delle specifiche EAI come scritte da Chris Marrin.

La parte più interessante della classe Oggetto è quella relativa alla creazione della nuova entità.

Qui di seguito riporto il sorgente corrispondente:

 
 
 

try {

  // Nodo per il planeSensor

  plane = browser.getNode("Sens");

  // Nodo Billboard

  bill = browser.getNode("Bill");

  // Nodo per il cursore

  cursor = browser.getNode("Cursor");
 
 

  // evento in uscita dal nodo PlaneSensor

  translation_changed = (EventOutSFVec3f) plane.getEventOut("translation_changed");

  translation_changed.advise(this, new Integer(3));
 
 

  // campi per settare la traslazione e la rotazione del cursore

  cursor_translation = (EventInSFVec3f) cursor.getEventIn("set_translation");

  cursor_rotation = (EventInSFRotation) cursor.getEventIn("set_rotation");

  bill_scale = (EventInSFVec3f) bill.getEventIn("set_scale");

  // risetto a 0

  cursor_translation.setValue(position);

  bill_scale.setValue(scale_cursor);
 
 

  // nodo radice al quale devono essere aggiunti i vari oggetti

  rootNode = browser.getNode("Root");

  rootChildren = (EventInMFNode) rootNode.getEventIn("addChildren");

  rootRemoveChildren = (EventInMFNode) rootNode.getEventIn("removeChildren");
 
 

  // current_node è il nodo che dovrà essere aggiunto

  // conterrà altri sotto-nodi

  current_node = browser.createVrmlFromString("Transform {}");
 
 

  // sensore di tocco da associare all'utente

  touch = browser.createVrmlFromString("TouchSensor {}");
 
 

  // tre livelli di Transform per introdurre le tre rotazioni

  transf_x = browser.createVrmlFromString("Transform {}");

  transf_y = browser.createVrmlFromString("Transform {}");

  transf_z = browser.createVrmlFromString("Transform {}");
 
 

  // tre rotazioni relative ai 3 nodi Transform precedenti

  // consentono di ruotare l'oggetto lungo tre diversi

  // assi

  // NB: le rotazioni non funzionano con Cosmo Player 1.0

  rot_x = (EventInSFRotation) transf_x[0].getEventIn("set_rotation");

  rot_y = (EventInSFRotation) transf_y[0].getEventIn("set_rotation");

  rot_z = (EventInSFRotation) transf_z[0].getEventIn("set_rotation");
 
 

  children = (EventInMFNode) current_node[0].getEventIn("addChildren");

  children.setValue(touch);

  children.setValue(transf_x);
 
 

  transfChildren_x = (EventInMFNode) transf_x[0].getEventIn("addChildren");

  transfChildren_y = (EventInMFNode) transf_y[0].getEventIn("addChildren");

  transfChildren_z = (EventInMFNode) transf_z[0].getEventIn("addChildren");
 
 

  // Creazione del nuovo nodo Shape

  nuovo_shape = browser.createVrmlFromString("Shape{}");

  nuovo_app = browser.createVrmlFromString("Appearance{}");

  nuovo_mat = browser.createVrmlFromString("Material{}");
 
 

  if (tipo == 0)

  nuovo_nodo = "Box{}"";

  if (tipo == 1)

  nuovo_nodo = "Cone{}"";

  if (tipo == 2)

  nuovo_nodo = "Cylinder{}"";

  if (tipo == 3)

  nuovo_nodo = "Sphere{}"";

  if (tipo == 4)

  nuovo_nodo = "Box{}"";
 
 

  nuovo_geo = browser.createVrmlFromString(nuovo_nodo);
 
 

  appearance = (EventInSFNode) nuovo_shape[0].getEventIn("appearance");

  appearance.setValue(nuovo_app[0]);

  material = (EventInSFNode) nuovo_app[0].getEventIn("material");

  material.setValue(nuovo_mat[0]);

  color = (EventInSFColor) nuovo_mat[0].getEventIn("set_diffuseColor");

  col[0] = red;

  col[1] = green;

  col[2] = blue;

  color.setValue(col);

  geometry = (EventInSFNode) nuovo_shape[0].getEventIn("geometry");

  geometry.setValue(nuovo_geo[0]);
 
 

  transfChildren_z.setValue(nuovo_shape);

  transfChildren_y.setValue(transf_z);

  transfChildren_x.setValue(transf_y);
 
 

  // traslazione e scala dell'oggetto

  translation = (EventInSFVec3f) current_node[0].getEventIn("set_translation");

  scale = (EventInSFVec3f) current_node[0].getEventIn("set_scale");
 
 

  // evento di pressione sul TouchSensor

  clicked = (EventOutSFBool) touch[0].getEventOut("isActive");

  clicked.advise(this, new Integer(2));
 
 
 
 

  // aggiungo di fatto il nodo alla Root

  rootChildren.setValue(current_node);
 
 
 

Non spaventatevi! Non è poi così complicato.

In sostanza vengono effettuate le seguenti operazioni: