Trabajo con cinemática inversa

Flash Player 10 y posterior, Adobe AIR 1.5 y posterior, requiere Flash CS4 o posterior

La cinemática inversa (IK) es una gran técnica para crear movimientos realistas.

La IK permite crear movimientos coordinados dentro de una cadena de partes conectadas denominada esqueleto IK, de modo que las partes se mueven juntas como en la vida real. Las partes del esqueleto son sus huesos y sus uniones. Dado el punto final del esqueleto, IK calcula los ángulos necesarios de las uniones para alcanzar dicho punto final.

Calcular estos ángulos manualmente sería todo un reto de programación. Lo atractivo de esta función es la posibilidad de crear esqueletos interactivamente con Adobe® Flash® Professional. Y, posteriormente, animarlos con ActionScript. La herramienta IK incluida con Flash Professional realiza los cálculos para describir el movimiento del esqueleto. Es posible limitar el movimiento a determinados parámetros del código ActionScript.

Como novedad la versión de IK de Flash Professional CS5, se presenta el concepto de muelle de huelo, normalmente asociado a aplicaciones con animaciones de alto nivel. Esta función, empleada con el nuevo motor de física dinámica, permite configurar movimientos similares a los de la vida real. Este efecto es visible en tiempo de ejecución y durante la edición.

Para poder crear esqueletos de cinemática inversa, es necesario disponer de una licencia para Flash Professional.

Fundamentos de cinemática inversa

La cinemática inversa (IK) permite crear animaciones reales uniendo distintas piezas de modo que puedan moverse entre sí con realismo.

Por ejemplo, se puede utilizar la cinemática inversa para mover una pierna hasta una posición determinada articulando los movimientos necesarios de las uniones de la pierna para lograr la postura deseada. La cinemática inversa utiliza una arquitectura de huesos unidos entre sí en una estructura denominada esqueleto IK. El paquete fl.ik sirve para crear animaciones de movimientos naturales y realistas. Permite animar varios esqueletos IK a la perfección sin necesidad de tener conocimientos físicos de algoritmos de cinemática inversa.

Puede crear el esqueleto IK con sus huesos y uniones correspondientes en Flash Professional. Luego puede acceder a las clases de IK para animarlos en tiempo de ejecución.

Consulte la sección Uso de cinemática inversa en el manual Uso de Flash Professional para obtener instrucciones detalladas sobre la creación de un esqueleto IK.

Conceptos y términos importantes

La siguiente lista de referencias contiene términos importantes que resultan relevantes para esta función:

Esqueleto
Cadena cinemática formada por huesos y uniones que se utiliza en animación por ordenador para simular movimientos con realismo.

Hueso
Segmento rígido de un esqueleto (análogo al hueso de un esqueleto animal)

Cinemática inversa (IK)
Proceso por el cual se determinan los parámetros de un objeto flexible unido denominado cadena cinemática o esqueleto.

Unión
Lugar en el que dos huesos entran en contacto, creado para permitir el movimiento de los huesos; es similar a la articulación de un animal.

Motor de física
Se utiliza un paquete de algoritmos relacionados con la física para proporcionar acciones reales de animación.

Muelle
Cualidad de un hueso que se mueve y reacciona cuando el hueso principal se mueve y posteriormente disminuye de forma incremental con el tiempo.

Información general sobre animación de esqueletos IK

Una vez creado el esqueleto IK en Flash Professional, utilice las clases de fl.ik para limitar su movimiento, realizar un seguimiento de sus eventos o animarlo en tiempo de ejecución.

En la siguiente figura se muestra un clip de película denominado Rueda. El eje es una instancia de un objeto IKArmature denominado Eje . La clase IKMover mueve el esqueleto en sincronía con la rotación de la rueda. El hueso IKBone ( ikBone2 ) del esqueleto se une a la rueda en su unión de cola.

A.
Rueda

B.
Eje

C.
ikBone2

En tiempo de ejecución, la rueda gira asociada a la interpolación de movimiento __motion_Wheel descrita en Descripción de la animación . Un objeto IKMover inicia y controla el movimiento del eje. En la siguiente figura se muestran dos instantáneas del esqueleto del eje asociado a la rueda giratoria en distintos fotogramas de la rotación.

Desplazamiento del esqueleto IK en dos posiciones distintas
En tiempo de ejecución, el siguiente código ActionScript:
  • Obtiene información sobre el esqueleto y sus componentes

  • Crea una instancia del objeto IKMover

  • Mueve el eje junto con la rotación de la rueda

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); 
    } 
}

Las clases IK utilizadas para mover el eje son:

  • IKArmature: describe el esqueleto, una estructura en árbol formada por huesos y uniones. Se debe crear con Flash Professional.

  • IKManager: clase contenedora de todos los esqueletos IK del documento. Se debe crear con Flash Professional.

  • IKBone: segmento de un esqueleto IK

  • IKJoint: conexión entre dos huesos IK

  • IKMover: inicia y controla el movimiento IK de los esqueletos

Para obtener información detallada y completa sobre estas clases, consulte el paquete ik .

Obtener información sobre un esqueleto IK

En primer lugar, declare variables para el esqueleto, el hueso y la unión que formen parte del grupo de piezas que desea mover.

El siguiente código utiliza el método getArmatureByName() de la clase IKManager para asignar el valor del esqueleto Axle a la variable tree de IKArmature. El esqueleto Axle se ha creado previamente con Flash Professional.

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

De forma similar, el siguiente código utiliza el método getBoneByName() de la clase IKArmature para asignar a la variable IKBone el valor del hueso ikBone2 .

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

La unión de cola del hueso ikBone2 es la parte del esqueleto que se une a la rueda giratoria.

La siguiente línea declara la variable endEffector y le asigna la propiedad tailjoint del hueso ikBone2 :

var endEffector:IKJoint = home.tailjoint;
La variable pos es un punto que almacena la posición actual de la unión endEffector .
var pos:Point = endEffector.position;

En este ejemplo, pos corresponde a la posición de la unión al final del eje, donde se conecta con la rueda. El valor original de esta variable se obtiene a partir de la propiedad position del objeto IKJoint.

Creación de una instancia de la clase IKMover y limitación del movimiento

Una instancia de la clase IKMover mueve el eje.

La siguiente línea crea una instancia del objeto ik de IKMover, transfiere a su constructor el elemento que desea mover y el punto de inicio del movimiento:
var ik:IKMover = new IKMover(endEffector, pos);

Las propiedades de la clase IKMover permiten limitar el movimiento de un esqueleto. Puede limitar el movimiento basado en la distancia, en las iteraciones o en el tiempo del movimiento.

Las siguientes parejas de propiedades refuerzan estos límites. La pareja consta de una valor booleano que indica si el movimiento está limitado y un entero que especifica dicho límite:

Propiedad booleana

Propiedad de entero

Límite establecido

limitByDistance:Boolean

distanceLimit:int

Establece la distancia máxima (en píxeles) que se mueve el motor IK en cada iteración.

limitByIteration:Boolean

iterationLimit:int

Especifica el número máximo de iteraciones que realiza el motor IK en cada movimiento.

limitByTime:Boolean

timeLimit:int

Establece el tiempo máximo (en milisegundos) asignado al motor IK para realizar el movimiento.

De forma predeterminada, todos los valores booleanos se establecen en false , por lo que el movimiento no se limita a no ser que se defina explícitamente un valor booleano como true . Para aplicar un límite, establezca la propiedad adecuada en true y después especifique un valor para la propiedad de entero correspondiente. Si establece el límite en un valor sin definir su propiedad Boolean correspondiente, el límite se obviará. En este caso, el motor IK sigue moviendo el objeto hasta llegar a otro límite o a la posición de destino del objeto IKMover.

En el siguiente ejemplo, la distancia máxima del movimiento del esqueleto se establece en 0,1 píxeles por iteración. El número máximo de iteraciones de cada movimiento se establece en diez.
ik.limitByDistance = true; 
ik.distanceLimit = 0.1; 
ik.limitByIteration = true; 
ik.iterationLimit = 10; 

Desplazamiento de un esqueleto IK

El objeto IKMover mueve el eje dentro del detector de eventos de la rueda. En cada evento enterFrame de la rueda, se calcula una nueva posición de destino para el esqueleto. Si se utiliza su método moveTo() , el objeto IKMover mueve la unión de cola hasta su posición de destino o tan lejos como lo permitan las limitaciones definidas por las propiedades limitByDistance , limitByIteration y 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 de muelles

La cinemática inversa de Flash Professional CS5 admite muelles de hueso. El muelle de hueso se puede establecer durante la edición y los atributos del muelle del hueso se pueden añadir o modificar en tiempo de ejecución. El muelle es una propiedad del hueso y sus uniones. Cuenta con dos atributos: IKJoint.springStrength , que establece la cantidad de muelle y IKJoint.springDamping , que añade resistencia al valor de intensidad y afecta al grado de descomposición del muelle.

La intensidad del muelle es un valor porcentual desde 0 (totalmente rígido, predeterminado) a 100 (muy suelto y controlado por física). Los huesos con muelle reaccionan al movimiento de su unión. Si no se activa ninguna otra traslación (rotación, x o y), los valores del muelle no se aplicarán.

La atenuación del muelle es un valor porcentual desde 0 (sin resistencia, predeterminado) a 100 (mucha atenuación). La atenuación cambia la cantidad de tiempo que transcurre entre el movimiento inicial del hueso y su vuelta a la posición de reposo.

Se puede verificar si los muelles están habilitados para un objeto IKArmature comprobando su propiedad IKArmature.springsEnabled . Las demás propiedades y métodos del muelle pertenecen a los objetos IKJoint independientes. Se puede habilitar una unión para la rotación angular y traslación a lo largo de los ejes x e y. Se puede situar un ángulo del muelle de la unión de rotación con IKJoint.setSpringAngle y una posición del muelle de la unión de traslación con IKJoint.setSpringPt .

Este ejemplo selecciona un hueso por nombre e identifica su valor tailJoint. El código prueba el esqueleto para ver si los muelles están habilitados y posteriormente establece las propiedades del muelle para la unión.

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 de eventos IK

La clase IKEvent permite crear un objeto de evento que contenga información sobre eventos IK. La información de IKEvent describe un movimiento que ha finalizado por haberse superado el tiempo especificado, la distancia o el límite de iteraciones.

El siguiente código muestra un detector de eventos y un controlador para realizar el seguimiento de los eventos de límite de tiempo. Este controlador de eventos informa sobre el tiempo, la distancia, el número de iteraciones y las propiedades de unión de un evento activado cuando se supera el límite de tiempo de IKMover.

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); 
}