Trabalho com cinemática inversa

O Flash Player 10 e superior, Adobe AIR 1.5 e superior, requerem o Flash CS4 ou superior

A IK (Cinemática inversa) é uma ótima técnica de criação de movimentos realistas.

A IK permite a criação de movimentos coordenados dentro de uma cadeia de trechos conectados conhecida como armadura IK, para que as partes apresentem movimentos sincronizados realistas. As partes da armadura são os bones e as junções. Dado o ponto final da armadura, a IK calcula os ângulos das junções que devem alcançar esse ponto.

Fazer os cálculos de tais ângulos manualmente seria desafiador. O mérito desse recurso é que você pode criar armaduras interativamente usando o Adobe® Flash® Professional. Em seguida, é só animá-las usando o ActionScript. O mecanismo IK incluído com o Flash Professional realiza os cálculos para descrever o movimento da armadura. É possível limitar o movimento a determinados parâmetros contidos em seu código ActionScript.

Uma novidade do Flash Professional CS5 da versão IK é o conceito de bone spring, normalmente associado com aplicativos de animação de ponta. Utilizado com o Physics Engine, este recursos permite configurar movimentos realísticos. Este efeito é visível no tempo de execução e durante a autoria.

Para criar armaduras de cinemática inversa, é preciso ter a licença do Flash Professional.

Noções básicas de cinemática inversa

A IK permite a criação de animações realistas por meio da junção de partes que se movimentam entre si.

Por exemplo, com o uso da IK você pode mover uma perna para uma determinada posição ao articular o movimento de suas respectivas junções para alcançar a posição desejada. A IK usa uma estrutura de bones encadeados em uma estrutura chamada armadura IK. O pacote fl.ik ajuda a criar animações que remetem a movimentos naturais. Ele permite que você anime várias armaduras IK diretamente sem precisar saber muito sobre o funcionamento dos algoritmos IK.

Crie a armadura IK com seus respectivos bones e junções auxiliares no Flash Professional. Em seguida, acesse as classes IK para animá-las no tempo de execução.

Consulte a seção Uso de cinemática inversa em Uso do Flash Professional para obter instruções detalhadas sobre como criar uma armadura IK.

Conceitos e termos importantes

A lista de referência a seguir contém termos importantes que são relevantes a este recurso:

Armadura
Cadeia cinemática, formada por bones e junções, utilizada em animações computadorizadas para simular movimentos reais.

Bone
é um segmento rígido de uma armadura, que corresponde a um dos ossos de um esqueleto.

Cinemática inversa (IK)
Processo de determinação dos parâmetros de um objeto com junções flexíveis, que pode ser uma cadeia cinemática ou uma armadura.

Junção
Local em que ocorre a união de dois bones, construída para permitir o movimento dos bones, que corresponde a uma articulação de um ser vivo.

Physics Engine
Um pacote de algoritmos de Física usados para criar ações realistas em animações.

Spring
A qualidade de um osso que se move e reage quando o osso ascendente é movimentado e, depois, diminui gradualmente ao longo do tempo.

Visão geral da animação de armaduras IK

Após criar uma armadura IK no Flash Professional, use as classes fl.ik para restringir seus movimentos, rastrear seus eventos e animá-la no tempo de execução.

A figura a seguir apresenta um clipe de filme chamado Roda. O eixo é uma ocorrência de uma IKArmature chamada Eixo . A classe IKMover move a armadura de modo sincronizado com a rotação da roda. O IKBone, ikBone2 , da armadura é anexado à roda, como junção de sua parte inferior.

A.
Roda

B.
Eixo

C.
ikBone2

No tempo de execução, a roda gira em associação com a interpolação de movimento __motion_Wheel discutida em Descrição da animação . Um objeto IKMover inicia e controla o movimento do eixo. A figura a seguir exibe dois instantâneos da armadura do eixo fixos à roda em diferentes quadros durante o movimento de rotação.

Movimentação da armadura IK em duas posições diferentes
No tempo de execução, o ActionScript a seguir:
  • Obtém informações sobre a armadura e seus componentes

  • Cria ocorrência de um objeto IKMover

  • Move o eixo de acordo com a rotação da roda

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

As classes IK usadas para mover o eixo são:

  • IKArmature: descreve a armadura, uma estrutura em árvore formada por bones e junções, que deve ser criada no Flash Professional

  • IKManager: classe de contêiner para todas as armaduras IK do documento, que deve ser criada no Flash Professional

  • IKBone: um segmento de uma armadura IK

  • IKJoint: uma conexão entre dois bones IK

  • IKMover: inicia e controla o movimento IK das armaduras

Veja descrições completas e detalhadas dessas classes no pacote ik .

Obtenção de informações sobre uma armadura IK

Primeiro, declare variáveis para a armadura, para o bone e para a junção que une as partes que deseja movimentar.

O código a seguir usa o método getArmatureByName() da classe IKManager para atribuir o valor da armadura Eixo à variável tree da IKArmature. A armadura Axle foi criada anteriormente no Flash Professional.

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

De modo semelhante, o código a seguir usa o método getBoneByName() da classe IKArmature para atribuir a variável IKBone ao valor do bone ikBone2 .

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

A junção da parte inferior do bone ikBone2 é a parte da armadura que a conecta à roda.

A linha a seguir declara a variável endEffector e atribui a ela a propriedade tailjoint do bone ikBone2 :

var endEffector:IKJoint = home.tailjoint;
A variável pos é um ponto que armazena a posição correta da junção endEffector .
var pos:Point = endEffector.position;

Nesse exemplo, pos é a posição da junção na extremidade do eixo conectada à roda. O valor original dessa variável é obtida a partir da propriedade position do IKJoint.

Ocorrência de IKMover e limitação de seu movimento

Uma ocorrência da classe IKMover movimenta o eixo.

A linha a seguir cria ocorrência do objeto ik do IKMover, transmitindo ao seu construtor o elemento a ser movimentado e o ponto de início do movimento:
var ik:IKMover = new IKMover(endEffector, pos);

As propriedades da classe IKMover permitem a limitação do movimento de uma armadura. É possível limitar o movimento, tendo como base a distância, as iterações e o tempo de duração do movimento.

Os pares de propriedades a seguir reforçam esses limites. Os pares consistem em um valor booliano que indica se o movimento é limitado, além de um inteiro que especifica o limite:

Propriedade Boolean

Propriedade Integer

Limite definido

limitByDistance:Boolean

distanceLimit:int

Define a distância máxima em pixels que o mecanismo IK se desloca para cada iteração.

limitByIteration:Boolean

iterationLimit:int

Define o número máximo de iterações que o mecanismo IK executa para cada movimento.

limitByTime:Boolean

timeLimit:int

Define o tempo máximo em milissegundos designado para que o mecanismo IK execute o movimento.

Por padrão, todos os valores boolianos são definidos como false , assim o movimento não é limitado a menos que você defina explicitamente um valor booliano como true . Para forçar um limite, defina a propriedade apropriada true e depois especifique um valor para a propriedade Integer correspondente. Se você definir o limite para um valor sem configurar sua propriedade Boolean correspondente, o limite será ignorado. Nesse caso, o mecanismo IK continua a movimentação do objeto até outro limite ou até que a posição de destino do IKMover seja alcançada.

No exemplo a seguir, a distância máxima do movimento da armadura está definido como 0,1 pixels por iteração. O número máximo de iterações para cada movimento está definido como dez.
ik.limitByDistance = true; 
ik.distanceLimit = 0.1; 
ik.limitByIteration = true; 
ik.iterationLimit = 10; 

Movimentação de uma armadura IK

O IKMover movimenta o eixo interno do ouvinte de eventos para a roda. Em cada evento enterFrame da roda, uma nova posição de destino para a armadura é calculada. Usando seu método moveTo() , o IKMover movimenta a junção da parte inferior para sua respectiva posição de destino ou o mais próximo possível, dentro dos limites definidos pelas suas propriedades 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); 
    } 
} 

Utilizando suspensões

A cinemática invertida o Flash Professional CS5 fornece suporte a bone spring. O bone spring pode ser configurado durante a autoria e seus atributos podem ser adicionados ou modificados em tempo de execução. Elasticidade (spring) é uma propriedade de um osso e de suas articulações. Ele possui dois atributos: IKJoint.springStrength , que define a quantidade de spring e IKJoint.springDamping , que adiciona resistência ao valor de força e altera a taxa de decaimento do spring.

A força do spring é um valor percentual de padrão 0 (totalmente rígido) até 100 (muito solto e controlado por propriedades físicas). Ossos com elasticidade reagem ao movimento de suas articulações. Se nenhuma outra translação (rotação, x, ou y) estiver ativada, as configurações de elasticidade não terão nenhum efeito.

O amortecimento de spring é um valor percentual de padrão 0 (nenhuma resistência) até 100 (muito reduzido). O amortecimento altera o tempo entre o movimento inicial o osso e o retorno à posição de descanso.

Verifique se os springs estão habilitados para um objeto IKArmature verificando a propriedade IKArmature.springsEnabled . As outras propriedades e os outros métodos da elasticidade pertencem a cada objeto IKJoint individualmente. Uma junta pode ser habilitada para rotação angular e transporte entre os eixo x e y. Você pode posicionar um ângulo de spring de junta com IKJoint.setSpringAngle e uma posição de junta de spring transportável com IKJoint.setSpringPt .

Este exemplo seleciona um osso pelo nome e identifica sua tailJoint. O código testa a armadura ascendente para saber se as elasticidades estão ativadas e, em seguida, define as propriedades de elasticidade da articulação.

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

A classe IKEvent permite a criação de um objeto de evento que contém informações sobre eventos IK. As informações IKEvent descrevem o movimento que foi interrompido porque o tempo especificado, a distância ou o limite de iteração foi excedido.

O código a seguir mostra um ouvinte de eventos e um manipulador para rastreamento de eventos de limite de tempo. Esse manipulador de eventos indica o tempo, a distância, a contagem de iterações e as propriedades de junções de um evento que dispara quando o limite de tempo do IKMover é excedido.

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