La cinematica inversa

Flash Player 10 e versioni successive, Adobe AIR 1.5 e versioni successive, richiede Flash CS4 o versioni successive

La cinematica inversa (IK) è un'ottima tecnica per la creazione di un movimento realistico.

La cinematica inversa consente di creare dei movimenti coordinati all'interno di una catena di parti connesse chiamata armatura IK, in modo che le parti si muovano contemporaneamente in modo realistico. Le parti dell'armatura sono le sue ossa e le sue articolazioni. Considerando il punto finale dell'armatura, IK calcola gli angoli necessari alle articolazioni perché raggiungano il punto terminale.

Calcolare questi angoli manualmente è un lavoro sicuramente complesso. Questa caratteristica è particolarmente interessante in quanto consente di creare delle armature in modo interattivo utilizzando Adobe® Flash® Professional. Le armature possono quindi essere animate utilizzando ActionScript. Il motore IK incluso con Flash Professional esegue i calcoli per descrivere il movimento dell'armatura. All'interno del vostro codice ActionScript, potete limitare il movimento secondo determinati parametri.

Una novità della versione Flash Professional CS5 di IK è il concetto di elasticità ossea, in genere associato con applicazioni di animazione di alto livello. Se usata insieme al nuovo motore fisico dinamico, questa caratteristica consente di configurare movimenti realistici. L'effetto è visibile sia durante la fase di runtime sia durante la fase di creazione.

Per creare armature con cinematica inversa, è necessario avere una licenza Flash Professional.

Nozioni di base sulla cinematica inversa

La cinematica inversa (inverse kinematics - IK) consente di creare delle animazioni che sembrano vive collegando delle parti in modo che si muovano l'una in relaziona all'altra in modo realistico.

Utilizzando l'IK è possibile, ad esempio, muovere una gamba in una certa posizione realizzando il movimento delle articolazioni della gamba necessario per raggiungere la posizione desiderata. L'IK utilizza un insieme di ossa collegate tra loro in una struttura chiamata armatura IK. Il pacchetto fl.ik consente di creare delle animazioni che riproducono il movimento naturale. Consente di animare diverse armature IK senza difficoltà e senza la necessità di conoscere i principi fisici che si celano dietro gli algoritmi IK.

Per prima cosa è necessario creare l'armatura IK formata da tutte le sue ossa e articolazioni utilizzando Flash Professional. Successivamente, per effettuare l'animazione in fase di runtime, è possibile accedere alle classi IK.

Per istruzioni dettagliate su come creare l'armatura IK, vedete la sezione Uso della cinematica inversa in Uso di Flash Professional .

Concetti e termini importanti

L'elenco di riferimento seguente contiene termini importanti correlati a questa funzione:

Armatura
Catena cinematica formata da ossa e articolazioni utilizzata nell'animazione al computer per simulare il movimento.

Osso
Segmento rigido dell'armatura corrispondente all'osso di uno scheletro animale.

Cinematica inversa (IK)
Processo per la determinazione dei parametri di un oggetto flessibile articolato detto catena cinematica o armatura.

Articolazione
Il punto di contatto tra due ossa, costruita per consentire il movimento delle ossa; simile a un'articolazione in un animale.

Motore fisico
Un pacchetto di algoritmi correlati alla fisica utilizzati per fornire azioni realistiche all'animazione.

Molla
La qualità di un osso che si muove e reagisce quando l'osso padre viene mosso e quindi diminuisce in maniera incrementale nel tempo.

Panoramica dell'animazione delle armature IK

Dopo aver creato un'armatura IK in Flash Professional, utilizzate le classi fl.ik per limitarne i movimenti, rintracciarne gli eventi e animarla in fase di runtime.

La seguente figura mostra un filmato denominato Wheel. L'asse è un'istanza di una armatura IK denominata Axle . La classe IKMover muove l'armatura in modo sincronico rispetto alla rotazione della ruota. L'osso IK IKBone2 all'interno dell'armatura è collegato alla ruota tramite l'articolazione posta alla sua estremità.

A.
Ruota

B.
Asse

C.
ikBone2

In fase di runtime, la ruota gira a seguito dell'interpolazione di movimento __motion_Wheel descritta nella sezione Descrizione dell'animazione . Un oggetto IKMover avvia e controlla il movimento dell'asse. La seguente figura mostra due istantanee dell'armatura dell'asse collegata alla ruota in due diverse fasi della rotazione.

Movimento dell'armatura IK in due diverse posizioni
In fase di runtime il seguente codice ActionScript:
  • Recupera le informazioni riguardanti l'armatura e i suoi componenti

  • Crea le istanze di un oggetto IKMover

  • Muove l'asse in sincrono rispetto alla rotazione della ruota

import fl.ik.* 
 
var tree:IKArmature = IKManager.getArmatureByName("Axle"); 
var bone:IKBone = tree.getBoneByName("ikBone2"); 
var endEffector:IKJoint = bone.tailJoint; 
var pos:Point = endEffector.position; 
 
var ik:IKMover = new IKMover(endEffector, pos); 
ik.limitByDistance = true; 
ik.distanceLimit = 0.1; 
ik.limitByIteration = true; 
ik.iterationLimit = 10; 
 
Wheel.addEventListener(Event.ENTER_FRAME, frameFunc); 
 
function frameFunc(event:Event) 
{ 
    if (Wheel != null) 
    { 
        var mat:Matrix = Wheel.transform.matrix; 
        var pt = new Point(90, 0); 
        pt = mat.transformPoint(pt); 
         
        ik.moveTo(pt); 
    } 
}

Le classi IK utilizzate per muovere l'asse sono:

  • IKArmature: descrive l'armatura, cioè la struttura ad albero formata da ossa e articolazioni; deve essere creata con Flash Professional

  • IKManager: classe contenente tutte le armature IK del documento; deve essere creata con Flash Professional

  • IKBone: segmento di un'armatura IK

  • IKJoint: collegamento tra due ossa (IKBone)

  • IKMover: avvia e controlla il movimento IK delle armature

Per una descrizione completa e dettagliata di queste classi, vedete il pacchetto ik .

Recupero delle informazioni su un'armatura IK

Per prima cosa dichiarare le variabili per l'armatura, l'osso e l'articolazione che compongono le parti che si desidera muovere.

Il seguente codice utilizza il metodo getArmatureByName() della classe IKManager per assegnare il valore dell'armatura Axle alla variabile IKArmature tree . L'armatura Axle è stata precedentemente creata con Flash Professional.

var tree:IKArmature = IKManager.getArmatureByName("Axle");

Allo stesso modo, il codice seguente utilizza il metodo getBoneByName() della classe IKArmature per assegnare alla variabile IKBone il valore dell'osso ikBone2 .

var bone:IKBone = tree.getBoneByName("ikBone2");

L'articolazione della parte terminale dell'osso ikBone2 è la parte dell'armatura che si collega alla ruota.

La seguente linea dichiara la variabile endEffector e l'assegna alla proprietà tailjoint dell'osso ikBone2 :

var endEffector:IKJoint = home.tailjoint;
La variabile pos è un punto che archivia la posizione corrente dell'articolazione endEffector .
var pos:Point = endEffector.position;

In questo esempio, pos è la posizione dell'articolazione della parte terminale dell'asse nel punto in cui si collega alla ruota. Il valore originale di questa variabile si ottiene dalla proprietà position di IKJoint.

Creazione dell'istanza IK Mover e limitazione del suo movimento.

Un'istanza della classe IKMover è responsabile del movimento dell'asse.

La seguente linea crea un'istanza dell'oggetto IKMover ik , trasmette alla sua funzione di costruzione l'elemento da muovere e il punto di avvio del movimento:
var ik:IKMover = new IKMover(endEffector, pos);

Le proprietà della classe IKMover consentono di limitare il movimento di un'armatura. Il movimento può essere limitato sulla base della distanza, delle iterazioni e del tempo del movimento.

Questi limiti vengono impostati tramite le seguenti coppie di proprietà. Le coppie sono formate da un valore booleano, che indica se il movimento è limitato, e da un intero, che specifica il limite:

Proprietà di tipo boolean

Proprietà di tipo integer

Impostazione limite

limitByDistance:Boolean

distanceLimit:int

Imposta la distanza massima in pixel consentita per il movimento del motore IK a ogni iterazione.

limitByIteration:Boolean

iterationLimit:int

Specifica il numero massimo di iterazioni eseguite dal motore IK per ogni movimento.

limitByTime:Boolean

timeLimit:int

Imposta il tempo massimo in millisecondi in cui il motore IK deve effettuare il movimento.

Per impostazione predefinita, tutti i valori booleani sono impostati su false , per cui il movimento non è limitato in alcun modo fino a quando non impostate esplicitamente un valore booleano su true . Per applicare un limite, impostate la proprietà appropriata su true e quindi specificate un valore per la proprietà di tipo integer corrispondente. Se impostate il limite su un valore senza impostare la relativa proprietà di tipo boolean, il limite viene ignorato. In questo caso, il motore IK continua a muovere l'oggetto fino a quando non raggiunge un altro limite o la posizione di destinazione di IKMover.

Nel seguente esempio, la distanza massima del movimento dell'armatura è impostata su 0,1 pixel per ogni iterazione. Il numero massimo di iterazioni per ogni movimento è impostato su 10.
ik.limitByDistance = true; 
ik.distanceLimit = 0.1; 
ik.limitByIteration = true; 
ik.iterationLimit = 10; 

Spostamento di un'armatura IK

IKMover muove l'asse all'interno del listener di eventi della ruota. In corrispondenza di ogni evento enterFrame della ruota, viene calcolata una nuova posizione di destinazione per l'armatura. Utilizzando il metodo moveTo , IKMover muove la parte terminale dell'articolazione verso la sua posizione di destinazione oppure alla velocità consentita dalle sue proprietà limitByDistance , limitByIteration e limitByTime .
Wheel.addEventListener(Event.ENTER_FRAME, frameFunc); 
 
function frameFunc(event:Event) 
{ 
    if (Wheel != null) 
    { 
        var mat:Matrix = Wheel.transform.matrix; 
        var pt = new Point(90,0); 
        pt = mat.transformPoint(pt); 
         
        ik.moveTo(pt); 
    } 
} 

Uso dell'elasticità

La cinematica inversa in Flash Professional CS5 supporta l'elasticità ossea. Questa caratteristica può essere impostata durante la fase di creazione e gli attributi di elasticità ossea possono essere aggiunti o modificati in fase di runtime. L'elasticità è una proprietà di un osso e delle sue articolazioni. Dispone di due attributi: IKJoint.springStrength , che imposta il grado di elasticità, e IKJoint.springDamping , che aggiunge resistenza al valore di forza e influenza la velocità di decadimento dell'elasticità.

La forza elastica è un valore percentuale compreso tra il valore predefinito 0 (completamente rigido) e 100 (estremamente libero e controllato dalla fisica). Le ossa con elasticità reagiscono al movimento della loro articolazione. Se non è abilitata nessun altra traslazione (rotazione, x o y), le impostazioni di elasticità non hanno effetto.

Lo smorzamento elastico è un valore percentuale compreso tra il valore predefinito 0 (nessuna resistenza) e 100 (fortemente smorzato). Lo smorzamento cambia l'intervallo di tempo tra il movimento iniziale di un osso e il suo ritorno nella posizione di riposo.

Potete verificare se l'elasticità è abilitata per un oggetto IKArmature controllando la sua proprietà IKArmature.springsEnabled . Le altre proprietà e metodi di elasticità appartengono a singoli oggetti IKJoint. Un'articolazione può essere abilitata per la rotazione angolare e la traslazione lungo gli assi x e y. Potete posizionare l'inclinazione elastica di un'articolazione rotazionale con IKJoint.setSpringAngle e la posizione elastica di un'articolazione traslazionale con setSpringPt .

In questo esempio un osso viene selezionato per nome e identificato il suo tailJoint. Il codice esegue il test dell'armatura padre per determinare se l'elasticità è abilitata e quindi imposta le proprietà dell'elasticità per l'articolazione.

var arm:IKArmature = IKManager.getArmatureAt(0); 
var bone:IKBone = arm.getBoneByName("c"); 
var joint:IKJoint = bone.tailJoint; 
if (arm.springsEnabled) { 
    joint.springStrength = 50; //medium spring strength 
    joint.springDamping = 10; //light damping resistance 
    if (joint.hasSpringAngle) { 
        joint.setSpringAngle(30); //set angle for rotational spring 
    } 
}

Uso di eventi IK

La classe IKEvent consente di creare un oggetto evento contenente le informazioni sugli eventi IK. Le informazioni IKEvent descrivono il movimento che è stato interrotto a causa del superamento del limite di tempo, di distanza o di iterazioni specificato.

Il seguente codice mostra un listener e un gestore di eventi per tenere sotto controllo gli eventi che limitano il tempo. Questo gestore di eventi effettua delle analisi su conteggi di tempo, distanza e iterazioni e sulle proprietà di articolazione di un evento che si attiva quando il limite di tempo di IKMover viene superato.

var ikmover:IKMover = new IKMover(endjoint, pos); 
ikMover.limitByTime = true; 
ikMover.timeLimit = 1000; 
 
ikmover.addEventListener(IKEvent.TIME_LIMIT, timeLimitFunction); 
 
function timeLimitFunction(evt:IKEvent):void 
{ 
    trace("timeLimit hit"); 
    trace("time is " + evt.time); 
    trace("distance is " + evt.distance); 
    trace("iterationCount is " + evt.iterationCount); 
    trace("IKJoint is " + evt.joint.name); 
}