sistema de animação avançado three.js

Eu mencionei AnimationMixer, AnimationAction, etc. no artigo de encadernação óssea avançada three.js . Na verdade, eles devem pertencer ao sistema de animação de Three.js. Este artigo apresentará sistematicamente o sistema de animação (Sistema de Animação).

prefácio

Em geral, raramente usamos o sistema de animação do three.js para criar animações manualmente - porque é realmente problemático. Uma maneira mais eficiente e conveniente é concluir diretamente a produção da animação em um software de modelagem como o Blender e, em seguida, criar animações em três .js .js para jogar. No entanto, aprender o sistema de animação ainda será útil para nós, vamos inserir o texto abaixo.

A criação de uma animação envolve três conceitos: quadros-chave Keyframes, faixas de quadro-chave KeyframeTracke clipes de animação AnimationClip.

1 quadro-chave Quadros-chave

O conceito de nível mais baixo no sistema de animação é o quadro-chave, cada quadro-chave consiste em três informações: tempo, atributo e valor, por exemplo:

  • No 0º segundo, positiono valor de é (0,0,0);
  • No 3º segundo, scaleo valor de é (1,1,1);
  • Aos 12 segundos, material.coloré vermelho.

Cada um desses três quadros-chave descreve o valor de alguma propriedade em um momento específico, mas os quadros-chave não designam nenhum objeto em particular. Os quadros-chave de posição podem ser usados ​​para animar qualquer objeto com uma propriedade .location, os quadros-chave de escala podem animar qualquer objeto com uma propriedade .scale e assim por diante. No entanto, os quadros-chave especificam os tipos de dados. Os quadros-chave acima positione scaleespecificam dados vetoriais, enquanto material.coloros quadros-chave especificam dados de cores. Atualmente, o sistema de animação suporta cinco tipos de dados.
insira a descrição da imagem aqui
Para criar uma animação, precisamos de pelo menos dois quadros-chave. O exemplo mais simples são dois quadros-chave numéricos, por exemplo, animando a opacidade de um material (quão transparente/transparente ele é):

  • No segundo 0, material.opacityé 0;
  • Aos 3 segundos, material.opacityé 1;

Uma opacidade de 0 significa completamente invisível e uma opacidade de 1 significa completamente visível. Quando definimos esses dois quadros-chave para um objeto, ele aparecerá gradualmente ao longo de 3 segundos. Independentemente da transparência original do objeto, os quadros-chave substituem seu valor original.

2 faixas de quadro-chave KeyframeTrack

Não há nenhuma classe que represente um único quadro-chave em Three.js, KeyframeTrackque contém duas matrizes — a matriz de tempo e a matriz de valor.Cada quadro-chave corresponde a um valor na matriz de tempo e na matriz de valor. Além disso, KeyframeTracké apenas uma classe base, não use diretamente KeyframeTrack, existem subclasses correspondentes para cada tipo de dados mencionado acima, você precisa selecionar a subclasse correspondente de acordo com o tipo de dados do valor:

  • BooleanKeyframeTrack
  • ColorKeyframeTrack
  • NumberKeyframeTrack
  • QuaternionKeyframeTrack
  • StringKeyframeTrack
  • VectorKeyframeTrack

2.1 NumberKeyframeTrack

Exemplo usando os quadros-chave de transparência anteriores:

  • Em 0 segundos, material.opacityé 0
  • Em 1 segundo, material.opacityé 1
  • Em 2 segundos, material.opacityé 0
  • Em 3 segundos, material.opacityé 1
  • Aos 4 segundos, material.opacityé 0

Como a transparência é numérica, NumberKeyframeTrackuma classe pode ser usada para armazenar dados de quadro-chave:

import {
    
     NumberKeyframeTrack } from "three";

const times = [0, 1, 2, 3, 4];
const values = [0, 1, 0, 1, 0];

const opacityKF = new NumberKeyframeTrack(".material.opacity", times, values);

Explicação: KeyframeTrackA função construtora é:

/**
 * KeyframeTrack构造函数
 * name: 关键帧轨道的名称
 * times: 关键帧时间数组,内部转换为Float32Array
 * values: 包含与时间数组相关的取值,内部转换为浮点32Array
 * interpolation: 要使用的插值类型,默认值为线性插值
 */
KeyframeTrack( name : String, times : Array, values : Array, interpolation : Constant )

2.2 VectorKeyframeTrack

Como NumberKeyframeTrackexiste apenas um valor do tipo numérico em cada ponto do tempo, o comprimento da matriz de tempos e a matriz de valores são os mesmos, e se os dados de cada quadro forem um vetor? Como a matriz de valores deve ser construída? Usamos o seguinte exemplo:

  • Em 0 segundos, positionpor(0,0,0)
  • Aos 3 segundos, positionpor(2,2,2)
  • Em 6 segundos, positionesses (0,0,0)
    três quadros-chave farão com que o objeto comece no centro da cena, mova-se para a direita, para cima e para frente por três segundos, depois inverta a direção e volte para o centro. Em seguida, usaremos esses quadros-chave para criar uma trilha vetorial.
import {
    
     VectorKeyframeTrack } from "three";

const times = [0, 3, 6];
const values = [0, 0, 0, 2, 2, 2, 0, 0, 0];

const positionKF = new VectorKeyframeTrack(".position", times, values);

positionDeve-se observar que, como os dados em cada ponto de tempo Vector3contêm 3 valores e esses dados são diretamente achatados, o comprimento da matriz de valores é três vezes maior que a matriz de tempos e a relação de mapeamento correspondente é:

const times = [0, 3, 6];
const values = [
  0,
  0,
  0, // (x, y, z) at t = 0
  2,
  2,
  2, // (x, y, z) at t = 3
  0,
  0,
  0, // (x, y, z) at t = 6
];

3 clipes de animação AnimationClip

O modelo dançante na figura abaixo (clique aqui para efeitos dinâmicos ) tem movimentos muito complexos: os pés giram, os joelhos dobram, os braços balançam descontroladamente e as cabeças balançam no ritmo. Cada movimento individual é armazenado em uma faixa de quadro-chave separada , de modo que uma faixa controla a rotação do pé esquerdo do dançarino, outra controla a rotação do pé direito e uma terceira controla a rotação do pescoço etc.
insira a descrição da imagem aqui

Na verdade, essa animação de dança é feita a partir de 53 faixas de quadro-chave, 52 das quais são faixas de quatérnios que controlam articulações individuais, como os joelhos, cotovelos e tornozelos do dançarino. Em seguida, há uma trilha .location que move o gráfico para frente e para trás no chão.

Essas 53 faixas de quadro-chave são combinadas para criar a animação final, que chamamos de clipe de animação. Um clipe de animação é, portanto, uma coleção de qualquer número de quadros-chave anexados a um único objeto, a classe que representa o clipe é AnimationClip. Os clipes de animação podem ser repetidos, portanto, embora a animação do dançarino tenha apenas 18 segundos de duração, quando chega ao fim, inicia a próxima rodada do loop, parecendo que o dançarino pode dançar para sempre.

Aqui está AnimationClipo construtor:

AnimationClip( name : String, duration : Number, tracks : Array )

Pode ser visto no construtor que o clipe de animação armazena três informações: o nome do clipe, a duração do clipe e a matriz de faixas que compõem o clipe. Se definirmos o comprimento como -1, a matriz de trilhas será usada para calcular o comprimento. Criamos um clipe contendo a faixa de posição única anterior:

import {
    
     AnimationClip, VectorKeyframeTrack } from "three";

const times = [0, 3, 6];
const values = [0, 0, 0, 2, 2, 2, 0, 0, 0];

const positionKF = new VectorKeyframeTrack(".position", times, values);

// 当前只有一个关键帧轨道
const tracks = [positionKF];

// 将length设置为-1可以自动从tracks中计算长度,在本例中为6秒
const length = -1;

const clip = new AnimationClip("slowmove", length, tracks);

Assim como os quadros-chave, AnimationClipeles não são anexados a nenhum objeto específico, portanto, como vincular a animação ao modelo e controlar sua reprodução?

4 Animation Mixer AnimationMixer

Para que os objetos (como o Mesh) acessem o sistema de animação e possam se mover, precisamos estabelecer uma conexão com o mixer de animação AnimationMixer. Cada objeto animado na cena requer um mixer separado . O mixer é responsável por fazer com que o modelo ajuste o estado de acordo com as configurações do clipe de animação, como mover os pés, braços e quadris de um dançarino ou mover as asas de um pássaro voando.

import {
    
     Mesh, AnimationMixer } from 'three';

// 创建一个静态的Mesh
const mesh = new Mesh();

// 通过将其连接到混合器,将其变为动画网格
const mixer = new AnimationMixer(mesh);

5 ação de animação AnimationAction

AnimationActionEle é responsável por conectar o objeto de animação ao clipe de animação AnimationClipe também é responsável por controlar a pausa, reprodução, reinicialização e outras operações da animação. Vale ressaltar que não iremos criar a ação diretamente, mas sim AnimationMixer.clipAction()com o auxílio de uma função, que pode ter melhor desempenho, pois o mixer fará o cache da ação.

Veja o exemplo abaixo:

import {
    
     AnimationClip, AnimationMixer } from "three";

const positionKF = new VectorKeyframeTrack(
  ".position",
  [0, 3, 6],
  [0, 0, 0, 2, 2, 2, 0, 0, 0]
);

const opacityKF = new NumberKeyframeTrack(
  ".material.opacity",
  [0, 1, 2, 3, 4, 5, 6],
  [0, 1, 0, 1, 0, 1, 0]
);

const moveBlinkClip = new AnimationClip("move-n-blink", -1, [
  positionKF,
  opacityKF,
]);

const mesh = new Mesh();

const mixer = new AnimationMixer(mesh);
const action = mixer.clipAction(moveBlinkClip);

5.1 Controle de ação múltipla

Suponha que temos um modelo de uma pessoa e esse modelo pode andar, correr e pular, cada animação aparecerá em um clipe separado e cada clipe deve estar conectado a uma ação. Então, assim como existe uma relação um-para-um entre Mixers e Models, também existe uma relação um-para-um entre Actions e AnimationClips:

const mixer = new AnimationMixer(humanModel);

const walkAction = mixer.clipAction(walkClip);
const runnAction = mixer.clipAction(runClip);
const jumpAction = mixer.clipAction(jumpClip);

O próximo passo é escolher qual dessas ações executar. Como você fará isso dependerá do tipo de cena que você está construindo. Por exemplo, no caso de um jogo, você conectaria essas ações aos controles do usuário para que, quando o botão correspondente for pressionado, o personagem caminhe, corra ou pule.

Referências

O Sistema de Animação three.js

Acho que você gosta

Origin blog.csdn.net/qq_26822029/article/details/130441062
Recomendado
Clasificación