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