Sou desenvolvedor de jogos e não estudei matemática. Então, eu só quero usar o Quaternions como uma ferramenta. E para poder trabalhar com rotação 3D, é necessário usar Quaternions (ou matrizes, mas vamos ficar em Quaternions aqui nesta pergunta). Eu acho que é importante para muitos desenvolvedores usá-los. É por isso que quero compartilhar meu conhecimento e espero preencher os buracos que tenho. Agora....
Então, tanto quanto eu entendi:
Um Quaternion pode descrever duas coisas:
- A orientação atual de um objeto 3d.
- A transformação de rotação que um Objeto poderia fazer. (rotationChange)
Você pode fazer com um Quaternion:
Multiplicações:
Quaternion endOrientation = Quaternion rotationChange * Quaternion currentOrientation;
Por exemplo: Meu objeto 3D é girado 90 ° para a esquerda - e minha rotação é uma rotação de 180 ° para a direita e, no final, meu objeto 3D 90 ° é girado para a direita.
Quaternion rotationChange = Quaternion endRotation * Quaternion.Inverse (startRotation);
Com isso, você obtém um rotationChange, que pode ser aplicado a outra orientação.
Vector3 endPostion = Quaternion rotationChange * Vector3 currentPosition;
Por exemplo: Meu objeto 3D está na posição (0,0,0) e minha rotação é multiplicada por uma rotação de 180 ° para a direita, minha posição final é algo como (0, -50,0). Dentro desse Quaternion existe um eixo - e uma rotação em torno desse eixo. Você gira seu ponto em torno desse eixo Y graus.
Vector3 rotatedOffsetVector = Quaternion rotationChange * Vector3 currentOffsetVector;
Por exemplo: Minha direção inicial está aparecendo PARA CIMA - (0,1,0), e minha rotação multiplicada é uma rotação 180 ° para a direita, minha direção final está aparecendo. (0, -1,0)
Mistura (Lerp e Slerp):
Quaternion currentOrientation = Quaternion.Slerp (startOrientation, endOrientation, interpolator)
se o interpolador for 1: currentOrientation = endOrientation
se o interpolador for 0: currentOrientation = startOrientation
Slerp interpola mais preciso, Lerp interpola mais desempenho.
Minhas perguntas):
Tudo o que expliquei até agora está correto?
Isso é "tudo" que você pode fazer com os Quaternions? (obv. não)
O que mais você pode fazer com eles?
Para que servem os produtos Dot e Cross entre 2 Quaternions?
Editar:
Pergunta atualizada com algumas respostas
fonte
n
orientações diferentes (atitudes, poses, etc.). Então você pode calculá-las usando pesos, generalizando efetivamente slerp / lerp. Você também pode converter um quaternion em um rotor, o que equivale a aplicar uma velocidade angular por um certo período de tempo a um corpo rígido. Portanto, você também pode descrever a integração da velocidade angular com os quaternions. Você também pode estimar quão diferentes são as duas orientações (calcule o comprimento do arco medido pelos dois quaterniões na hiperesfera).Respostas:
Multiplicação
Pelo menos em termos da implementação de Quaternions pela Unity, a ordem de multiplicação descrita na pergunta não está correta. Isso é importante porque a rotação 3D não é comutativa .
Então, se eu quiser rotacionar um objeto,
rotationChange
começando pelo seu,currentOrientation
eu o escreveria assim:(ie. As transformações se acumulam à esquerda - o mesmo que a convenção matricial do Unity. A rotação mais à direita é aplicada primeiro / no final "mais local")
E se eu quisesse transformar uma direção ou deslocar um vetor por uma rotação, escreveria assim:
(O Unity gerará um erro de compilação se você fizer o oposto)
Misturando
Na maioria dos casos, você pode se safar das rotações de leitura. Isso ocorre porque o ângulo usado "sob o capô" em um quaternion é metade do ângulo de rotação, tornando-o substancialmente mais próximo da aproximação linear de Lerp do que algo como uma Matrix (que geralmente não funciona bem com Lerp!). Confira cerca de 40 minutos deste vídeo para obter mais explicações .
O único caso em que você realmente precisa do Slerp é quando você precisa de velocidade consistente ao longo do tempo, como a interpolação entre quadros-chave em uma linha do tempo da animação. Nos casos em que você apenas se importa que uma saída seja intermediária entre duas entradas (como mesclar camadas de uma animação), geralmente o Lerp serve muito bem.
O quê mais?
O produto escalar de dois quaternions de unidades fornece o cosseno do ângulo entre eles, para que você possa usar o produto escalar como uma medida de similaridade, se precisar comparar rotações. Porém, isso é um pouco obscuro; portanto, para um código mais legível, eu usaria frequentemente o Quaternion.Angle (a, b) , que expressa mais claramente que estamos comparando ângulos, em unidades familiares (graus).
Esses tipos de métodos de conveniência que o Unity fornece para o Quaternions são super úteis. Em quase todos os projetos, uso este aqui pelo menos algumas vezes :
Isso cria um quaternion que:
forward
argumento do vetorup
argumento do vetor, se fornecido, ou para(0, 1, 0)
se omitidoA razão pela qual o "up" fica "o mais próximo possível" é que o sistema está sobredeterminado. Enfrentar z + para
forward
usa até dois graus de liberdade (ou seja, guinada e inclinação), então temos apenas um grau de liberdade restante (rolagem).Acho que muitas vezes quero algo com as propriedades de exatidão opostas: quero que o local y + aponte exatamente ao longo
up
, e o local z + fique o mais próximo possívelforward
da liberdade restante.Isso ocorre, por exemplo, ao tentar formar um quadro de coordenadas relativo à câmera para entrada de movimento: eu quero que minha direção local acima permaneça perpendicular ao chão ou à superfície inclinada normal, para que minha entrada não tente encapsular o caractere no terreno ou levite-os para fora dele.
Você também pode conseguir isso se quiser que o compartimento da torre de um tanque enfrente um alvo, sem sair do corpo do tanque ao mirar para cima / para baixo.
Podemos criar nossa própria função de conveniência para fazer isso, usando
LookRotation
para o trabalho pesado:Aqui, giramos primeiro o local y + para z + e o local z + para y-.
Em seguida, rotacionamos o novo z + em nossa direção para cima (para que o resultado líquido seja local y + aponta diretamente ao longo
exactUp
) e o novo y + o mais próximo possível da direção para frente negada (para que o resultado líquido seja local z + pontos o mais próximo possível ao longoapproximateForward
)Outro método prático de conveniência é o
Quaternion.RotateTowards
que costumo usar da seguinte maneira:Isso nos permite chegar
targetRotation
a uma velocidade consistente e controlável, independentemente da taxa de quadros - importante para rotações que afetam o resultado / imparcialidade da mecânica de jogo (como girar o movimento de um personagem ou rastrear a torre do jogador). Ingenuamente Ler / Slerping nessa situação pode facilmente levar a casos em que o movimento fica mais rápido em altas taxas de quadros, afetando o equilíbrio do jogo. (Isso não quer dizer que esses métodos estejam errados - há maneiras de usá-los corretamente sem alterar a imparcialidade, apenas requer cuidado.RotateTowards
Fornece um atalho conveniente que cuida disso para nós)fonte
Onde é usado o produto escalar?
No Unity, um dos usuários mais comuns do produto escalar é sempre que você verifica se dois quaternions são iguais via
==
ou!=
. O Unity calcula o produto escalar para verificar a similaridade em vez de comparar diretamente os valores internos x, y, z, w. Vale a pena manter isso em mente, pois torna a ligação mais cara do que você imagina.Também o usamos em um caso de uso interessante também ..
Diversão com produtos quaternion dot - Mundos esféricos e orbitais
Simulações de planetas inteiros e até sistemas solares inteiros estão se tornando cada vez mais comuns. Para fazer isso em tempo real, precisamos também do produto quaternion dot. Muitos deles. O produto quaternion dot é muito subutilizado, mas certamente tem seus usos - vamos dar uma olhada!
Em primeiro lugar, temos toda uma série de rotações a considerar:
Combine-os todos juntos e você terá muita complexidade (e muitos números enormes!). Quando o espectador está de pé na superfície do planeta, não queremos que ele se apresse a uma velocidade louca pelo espaço no mundo dos jogos. Na verdade, preferimos que eles estejam imóveis e em algum lugar perto da origem - mova o universo ao redor do jogador.
É importante ressaltar que, para que possamos obter a rotação e a inclinação do planeta corretas nesse cenário, precisamos travar o polo no eixo para que ele possa apenas subir / descer na imagem acima (por exemplo, balançar "para cima" enquanto o jogador viaja norte). É aí que entra um produto de ponto de quaternário. Se não usássemos um produto de ponto aqui e, em vez disso, apenas multiplicássemos a inclinação, isso aconteceria:
Observe como os pólos de nossos 'planetas' orbitais estão sempre se inclinando em direção à estrela. Não é isso que acontece na realidade - a inclinação está em uma direção fixa .
Sem ir muito longe do tópico, aqui está um breve resumo:
Ao obter apenas o ângulo, eliminamos parte dessa rotação indesejada . Ao mesmo tempo, também terminamos com uma medida de longitude útil para a navegação e para o clima local.
* Os planetas são construídos a partir de muitas células da grade . Somente os próximos são realmente exibidos.
fonte
dot(a, b) = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w
em oposição à composição de quaternário que usamos para encadear rotações) nos ajudaria a resolver esse problema. Eu ficaria feliz em votar se você puder elaborar isso um pouco mais tarde (não pretendo mantê-lo longe do seu pijama ... quero dizer, durma!)