Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 20 di 51
  • livello principiante
Indice lezioni

Trasformazioni automatiche

Animiamo il mondo 3d in modo automatico o quando avviene un evento specifico
Animiamo il mondo 3d in modo automatico o quando avviene un evento specifico
Link copiato negli appunti

Qualche volta può capitare di voler creare delle trasformazioni interattive, attivabili utilizzando la tastiera o semplicemente muovendo il mouse sullo stage.

Inoltre, per certi scopi, può essere necessario far muovere automaticamente degli oggetti, senza alcun intervento dell'utente.

Sandy offre metodi più o meno elaborati per animare il proprio mondo 3D!

Per i movimenti più semplici è possibile utilizzare il "solito" oggetto Transform3D, creando però degli eventi temporizzati per le animazioni, piuttosto che basarsi sugli interventi dell'utente. Chi ha utilizzato il metodo onEnterFrame di Flash avrà familiarità con questo metodo: l'enterFrame infatti richiama una determinata serie di azioni a ogni fotogramma, per cui, ad esempio, se il frame rate è di 12 frame al secondo (fps), le azioni presenti nell'evento EnterFrame si verificheranno ogni 1/12 di secondo.

Allo stesso modo, all'interno dell'oggetto World3D di Sandy, c'è un evento, onRenderEvent, che viene richiamato ogni volta che la scena viene renderizzata, ovvero per ogni "frame" della scena di Sandy.

Nell'esempio creeremo una rotazione automatica di un gruppo (che conterrà il "solito" cubo). Dovremo pertanto implementare l'intercettazione dell'evento onRenderEvent e preparare una funzione che aggiorni l'angolo di rotazione e di conseguenza modifichi l'oggetto sulla scena.

Nel file di esempio, per rendere l'effetto più gradevole, è stata usata una trasformazione combinata e il cubo ha una traslazione iniziale di 25,25,0.

Il pannello inserito all'interno del filmato, per avviare la rotazione, questa volta, ha tre pulsanti che permettono di scegliere su quale asse far ruotare il cubo, e due pulsanti "Run" e "Stop" per avviare o interrompere l'animazione.

Per mantenere memorizzato il valore della rotazione in ogni momento utilizzeremo le variabili xRot, yRot e zRot , mentre per l'angolazione del box utilizzeremo le variabili xDel, yDel e zDel.

Listato 22. Gestisce l'evento onRenderEvent

// Gestione degli eventi
function createHandlers(){
    // Ogni volta che si verifica l'onRenderEVENT, viene chiamata la funzione rotate
    world.addEventListener (World3D.onRenderEVENT, this, rotate);
    
    // Il bottone startButton avvia la rotazione
    startButton.onRelease = function(){
        running = true;
    }
    // il bottone stopButton invece la ferma
    stopButton.onRelease = function(){
        running = false;
    }
    
    // A seconda del pulsante premuto viene scelto l'asse di rotazione
    xRotButton.onRelease = function(){
        xDel = angleStep;
        yDel = zDel = 0;
    }
    yRotButton.onRelease = function(){
        yDel = angleStep;
        xDel = zDel = 0;
    }
    zRotButton.onRelease = function(){
        zDel = angleStep;
        xDel = yDel = 0;
    }
}

Per ogni fotogramma di Sandy (quindi per ogni volta che si verifica l'evento onRenderEvent), viene richiamata la funzione rotate(), che aumenta la rotazione.

I bottoni di avvio e arresto dell'animazione semplicemente impostano la variabile running su true o su false; tale variabile viene utilizzata dalla funzione rotate() per stabilire se eseguire o meno il movimento.

Se guardiamo il codice associato all'evento onRelease del pulsante xRotButton, possiamo vedere che imposta la variabile xDel al valore di angleStep, mentre yDel e zDel vengono impostate a zero, ciò per impostare l'asse X come asse di rotazione; le azioni associate a yRotButton e zrotButton hanno lo stesso scopo per i rispettivi assi.

Vediamo infine la funzione rotate(), che si occupa di ruotare il cubo all'interno della scena.

Listato 23. Ruota il cubo all'interno della scena

function rotate(){
    if( running ){
        xRot += xDel; yRot += yDel; zRot += zDel;
        rotation.rot( xRot, yRot, zRot );
    }
}

Vediamo che, se la variabile running è impostata su true, la funzione calcola i nuovi valori per la rotazione attorno ai tre assi, quindi tramite la funzione rot() dell'oggetto Transform3D applica la rotazione con i nuovi valori. Il valore di angleStep verrà incrementato per l'asse di rotazione scelto dall'utente, mentre rimarrà invariato per altri due assi:

Rotazione automatica su un asse

Dopo aver provato i pulsanti poniamoci le seguenti domande: c'è un punto del cubo che non si sposta mai dalla sua posizione originale? La rotazione avviene come ci aspettiamo di vedere?

Per la seconda domanda, suppongo che la risposta sia no, non sempre. Il motivo è l'ordine della rotazione intorno agli assi; ecco cosa dice la documentazione di Sandy riguardo alla funzione rot():

public function rot(px:Number, py:Number, pz:Number):Void
Realize the euler rotation matrix based on the three angles in degrees.
Parameters
px Number Angle of rotation in degrees around the X axis
py Number Angle of rotation in degrees around the Y axis
pz Number Angle of rotation in degrees around the Z axis

Non troviamo molte informazioni riguardo al nostro problema, ma notiamo che vengono menzionate le matrici di Euler (possiamo trovare molte informazioni su internet): per i matematici più bravi, consiglio il link "Euler angles", dove sono riportate discussioni e calcolo delle matrici. Per i meno esperti, consiglio una rapida occhiata a "Euler Angles are Evil", dove si trova una spiegazione meno "tecnica".

Possiamo concludere dicendo che per avere una rotazione "pulita" intorno a un asse per volta, sarebbe necessario utilizzare tre TransformGroup e tre Transform3D, uno per ogni asse.

"© Petit Publications 2006" - diritti riservati

Ti consigliamo anche