Patas que ficam plantadas: IK de dois ossos em Molang para o Doggoyle

Como o Doggoyle do LLS Magic Pack mantém as patas no chão a passo, a trote e a galope: um relógio de passada a partir da velocidade no chão, pisadas planejadas no piso, e cinemática inversa resolvida em todo quadro no Molang do Bedrock.

· 7 min de leitura

O Doggoyle do LLS Magic Pack enrolado dormindo

A maioria das criaturas do Minecraft anda balançando as pernas para a frente e para trás numa onda senoidal. É barato e numa vaca fica bem, mas os pés deslizam: a perna balança numa velocidade, o corpo anda em outra, e as patas patinam no chão. Num cão de pedra grande e pesado, com patas compridas e com garras, essa patinação é a primeira coisa que se nota.

O Doggoyle, o cão de guarda dos hoggoyles no Magic Pack, faz ao contrário. Primeiro se planeja no chão onde cada pata vai, e a perna dobra para colocar ela lá. Isso é cinemática inversa, e no Bedrock ela precisa rodar em Molang, a linguagem de expressões do pacote de texturas, em todo quadro, no dispositivo do jogador.

Por que a perna precisa ser resolvida

Animar uma perna normalmente quer dizer definir ângulos nas articulações: tanto no ombro, tanto no cotovelo. A pata termina onde esses ângulos colocarem. A cinemática inversa inverte isso: você diz para onde a pata vai, e resolve os ângulos.

A pata dianteira e a traseira de um cachorro são, cada uma, dois ossos compridos com uma articulação no meio, que é o caso clássico de dois ossos:

  • Pata dianteira: o ombro em cima, o cotovelo atrás dele, e o antebraço inclinado para a frente até o punho.
  • Pata traseira: o quadril, a soldra para a frente, a tíbia para trás até o jarrete, e depois um metatarso quase vertical até a pata.

Com a raiz (ombro ou quadril), o alvo (punho ou jarrete) e o comprimento dos dois ossos, a dobra tem exatamente uma resposta de cada lado. Para que lado ela dobra é o que faz dela uma perna de cachorro e não de pássaro: cotovelos dobram para trás, soldras para a frente.

A resolução em si são duas funções de Molang: math.atan2 para a direção da raiz até o alvo, e math.acos com a lei dos cossenos para quanto cada articulação dobra para cobrir a distância. O Molang do Bedrock trabalha em graus, o que ajuda; a rotação do osso é então o ângulo de repouso, menos a inclinação do pai, menos o ângulo resolvido. Quatro pernas, quatro resoluções, em todo quadro.

Passo 1: um relógio de passada que sabe a que velocidade está

Antes de planejar as pisadas você precisa saber em que ponto da passada o cachorro está. A entrada óbvia é q.modified_distance_moved, o contador de balanço dos membros que as criaturas normais usam. Ele não é em blocos: corre a mais ou menos quatro vezes a distância e tem limite. Uma passada medida por ele sai errada em qualquer velocidade. (Esse está num texto anterior sobre bugs silenciosos do Bedrock.)

Então o relógio do Doggoyle roda com q.ground_speed, a velocidade real sobre o chão, integrada numa fase de passada. O contador é só um reserva. O andamento também vem da velocidade:

AndamentoPadrão de pisadas
PassoQuatro tempos: traseira esquerda, dianteira esquerda, traseira direita, dianteira direita, a um quarto de passada uma da outra
TrotePares na diagonal: traseira esquerda com dianteira direita, e depois o outro par meia passada mais tarde
GalopeO galope rotativo de um cachorro: traseira esquerda, traseira direita, dianteira direita, dianteira esquerda, em volta do corpo

Mudar de andamento move cada perna para a frente no ciclo dela até o novo tempo, nunca para trás, então não tem perna tremendo para trás na troca de andamento.

Passo 2: planejar a pata no chão

Cada perna tem uma fase na passada. Parte da passada ela fica embaixo (o apoio), o resto fica em cima (o voo).

  • Embaixo: a pata varre para trás em linha reta, exatamente na velocidade em que o chão anda embaixo do cachorro. A varredura é o comprimento da passada vezes a fração da passada em que a pata fica embaixo. Se isso bate, uma pata apoiada não se mexe em relação ao chão. É essa a ideia toda.
  • Em cima: a pata vai para a frente numa curva de Hermite cujas velocidades em cada ponta batem com o apoio, então não tem tranco na saída nem no toque.

A pata também inclina: o calcanhar sobe no fim do apoio enquanto os dedos ficam embaixo, e volta no voo. Essas patas são compridas (as garras vão sete unidades à frente do punho), então uma pata dobrada precisa levantar o punho para passar pelo chão. Quanto levantar é calculado a partir da dobra, não chutado, mais uma folguinha.

Depois a IK pega os alvos do punho e do jarrete e dobra as pernas para alcançar.

Conferi fora do jogo com a mesma matemática que o Molang roda, em todo andamento: uma pata apoiada anda menos de 0,4 unidade durante um apoio.

O que deu errado, e como cada coisa foi pega

Cada uma destas foi achada por uma verificação numérica (uma quebra na curva de uma articulação, uma pata abaixo do chão) e não no olho. Ver uma animação em velocidade normal esconde muita coisa.

Um limite duro de alcance quebra o cotovelo

A galope total, o alvo de uma pata pode estar mais longe do que a perna alcança. A correção óbvia, math.clamp na distância, trava o cotovelo totalmente reto e depois solta: um estalo visível no fim de todo alcance.

A correção é um limite suave. A menos de uma unidade do alcance total, a distância vai freando de forma exponencial em vez de parar seco:

reach = d < dmax - 1 ? d : dmax - math.exp(dmax - 1 - d)

A perna estica suave e nunca chega a travar.

Uma pata que dobra demais, dobra duas vezes

Patas compridas têm uma propriedade chata: as pontas das garras ficam mais baixas por volta de 70 graus de dobra. A primeira versão levantava o calcanhar, dobrava e erguia a pata em três curvas separadas juntadas com max(), e a dobra passava dos 70 graus duas vezes por voo. Então o quanto o punho precisava subir tinha duas corcovas, e o cotovelo dobrava duas vezes por passada.

Agora a flexão inteira da pata é uma corcova suave só, um cosseno elevado: começa quando o calcanhar sobe, chega ao máximo cedo no voo, e já achatou aos 85% do voo para a pata pousar reta. A dobra tem limite para nunca passar do ponto mais baixo.

Levante demais uma pata traseira e a coxa dá uma chicotada

A pata traseira dobra bem menos que a dianteira. Levantada tão alto quanto a da frente, ela colocava o jarrete bem do lado do quadril, e perto de uma linha reta passando pela raiz a resolução é hipersensível: a coxa girou 50 graus em dois quadros.

O balanço do corpo afunda as patas de um lado

Um cachorro trotando balança, o que abaixa um ombro e levanta o outro. Com uma altura de raiz só, compartilhada, as patas do lado baixo entravam no chão. Agora cada perna recebe a própria altura de raiz a partir do balanço, então o lado baixo dobra mais e o lado alto estica.

Ombros que balançam como porta

O primeiro modelo fazia o ombro numa peça só com o braço, uma placa até a cernelha. Cada passo balançava a placa inteira pelo corpo como um pêndulo. O ombro e a garupa agora são blocos fixos no corpo, com o membro encaixado dentro deles.

Misturando poses: misture onde a pata vai, não os ângulos

O Doggoyle pula, aterrissa, senta, deita e nada na água. O primeiro pulo misturava dois conjuntos de ângulos de articulação: a pose correndo e a pose no ar. Misturar ângulos produz uma perna mais comprida que as duas, então nos primeiros quadros de toda aterrissagem as patas entravam 1,4 unidade no chão.

Agora a mistura é de onde a pata vai, e a mesma IK resolve a perna em todo quadro a partir disso. A inclinação da pata funciona igual: cancela a rotação da cadeia inteira e depois soma uma inclinação misturada só, no mundo, então uma pata nunca passa pela posição de dedos para baixo enquanto está perto do chão.

Queixos atravessando o chão

Sentar, deitar e se enrolar foram posados na mão, e cada um ficava certo sozinho. Aí o corpo descia para deitar e o queixo atravessava o chão. As poses de repouso agora são resolvidas contra o chão (uma busca por bissecção da altura em que o queixo passa raspando), e tem um protetor de queixo em todo quadro: qualquer que seja a mistura de estados do cachorro, a altura do queixo é calculada a partir do corpo, e ela nunca fica abaixo do chão.

Tudo roda em Molang

Tudo isto fica nos scripts pre_animation da entidade do cliente, que rodam em todo quadro antes das animações. O Molang tem funções com número fixo de argumentos (math.max aceita exatamente dois, e com três quebra a entidade inteira calado) e para se você lê uma variável antes de definir, então a ordem das linhas importa tanto quanto a matemática. O modelo, a animação e o Molang são gerados juntos por um script só, que também roda as verificações acima antes de escrever qualquer coisa.

Conheça o Doggoyle nas masmorras de enxofre do Magic Pack. Dome um com uma maçã dourada normal; o guia do Magic Pack explica como achar uma masmorra.

O mod

Mais do devlog

← Todo o devlog