Eu tenho um Vector3 que tem um ângulo de euler para cada eixo.
Normalmente, quando eu quero criar uma matriz de rotação, usarei funções como D3DXMatrixRotationX passando o ângulo respectivo do meu vetor de rotação acima e multiplico as matrizes (ZXY) para criar a matriz de rotação geral usada para formar a matriz de transformação de objeto completa.
No entanto, esse método produzirá um conjunto de rotações no espaço do objeto. Ou seja, passar um vetor de (90, 0, 90) para o meu método criará uma rotação no espaço mundial efetivamente de (90, 90, 0).
Existe uma maneira de sempre garantir que cada componente do meu vetor de rotação resulte em uma rotação em torno dos respectivos eixos alinhados ao espaço mundial?
EDITAR:
Esta é uma animação do que está acontecendo atualmente - eu quero uma maneira de girar em torno dos eixos azuis, não do vermelho.
EDIT 2:
Apenas para observar, não estou procurando uma solução que envolva os ângulos de Euler, mas simplesmente uma maneira de representar uma transformação de múltiplas rotações nos eixos mundiais.
fonte
Respostas:
Com base nos seus comentários, parece que você está armazenando a orientação do objeto como um conjunto de ângulos de Euler e diminuindo / diminuindo os ângulos quando o jogador gira o objeto. Ou seja, você tem algo parecido com este pseudocódigo:
Como observa Charles Beattie , como as rotações não são comutadas, isso não funcionará conforme o esperado, a menos que o jogador gire o objeto na mesma ordem em que
eulerAnglesToMatrix()
as rotações são aplicadas.Em particular, considere a seguinte sequência de rotações:
Na representação ingênua do ângulo de Euler, conforme implementado no pseudocódigo acima, essas rotações serão canceladas e o objeto retornará à sua orientação original. No mundo real, isso não acontece - se você não acredita em mim, pegue um dado de seis lados ou um cubo de Rubik, deixe x = y = 90 ° e experimente você mesmo!
A solução, como você observa em sua própria resposta , é armazenar a orientação do objeto como uma matriz de rotação (ou um quaternion) e atualizar essa matriz com base nas informações do usuário. Ou seja, em vez do pseudocódigo acima, você faria algo assim:
(Tecnicamente, como qualquer matriz de rotação ou quaternion pode ser representada como um conjunto de ângulos de Euler, é possível usá-los para armazenar a orientação do objeto. Mas a regra fisicamente correta para combinar duas rotações sequenciais, cada uma representada como ângulos de Euler, em uma única rotação é bastante complicado e equivale essencialmente a converter as rotações em matrizes / quaternions, multiplicando-as e convertendo o resultado novamente em ângulos de Euler.)
fonte
O problema das rotações é que, a maioria das pessoas pensa nisso em termos de ângulos de Euler, pois são fáceis de entender.
No entanto, a maioria das pessoas esquece o ponto em que Euler são três ângulos seqüenciais . Isso significa que a rotação ao redor do primeiro eixo fará com que a próxima rotação seja relativa à primeira rotação original; portanto, você não pode girar independentemente um vetor em torno de cada um dos três eixos usando ângulos de Euler.
Isso se traduz diretamente em matrizes quando você multiplica duas matrizes. Você pode pensar nessa multiplicação como transformar uma matriz no espaço da outra matriz.
Isso deve acontecer com quaisquer três rotações sequenciais, mesmo ao usar quaternions.
Quero enfatizar o fato de que os quaternions não são uma solução para o bloqueio flexível. Na verdade, o bloqueio flexível sempre acontecerá se você representou os ângulos de Euler usando quaterniões. O problema não é a representação, o problema é a três etapas seqüenciais.
A solução?
A solução para girar um vetor em torno de 3 eixos de forma independente é combinar um único eixo e um único ângulo, dessa forma você pode se livrar da etapa em que é necessário fazer uma multiplicação seqüencial. Isso se traduzirá efetivamente em:
Minha matriz de rotação representa o resultado da rotação em torno de X, Y e Z.
ao invés da interpretação de Euler de
Minha matriz de rotação representa a rotação em torno de X, depois Y e Z.
Para esclarecer isso, citarei o teorema da rotação de wikipedia Euler:
Observe que a multiplicação de 3 matrizes sempre representará 3 rotações seqüenciais.
Agora, para combinar rotações em torno de 3 eixos, é necessário obter um único eixo e ângulos únicos que representam a rotação em torno de X, Y, Z. Em outras palavras, você precisa usar uma representação de eixo / ângulo ou quaternário para se livrar das rotações seqüenciais.
Isso geralmente é feito, iniciando com uma orientação inicial (a orientação pode ser vista como um ângulo de eixo), geralmente representada como um quaternião ou um ângulo de eixo, e modificando essa oração para representar sua orientação de destino. Por exemplo, você começa com a pergunta de identidade e depois gira pela diferença para alcançar a orientação de destino. Dessa forma, você não perde nenhum grau de liberdade.
fonte
Mudar uma combinação de rotações do espaço do objeto para o espaço do mundo é trivial: basta reverter a ordem em que as rotações são aplicadas.
No seu caso, em vez de multiplicar matrizes
Z × X × Y
, você só precisa calcularY × X × Z
.Uma justificativa para isso pode ser encontrada na Wikipedia: conversão entre rotações intrínsecas e extrínsecas .
fonte
Z
(espaço do objeto), depois 50 graus ao redorX
(espaço do objeto) e 45 graus ao redorY
(espaço do objeto). É exatamente o mesmo que uma rotação de 45 graus ao redorY
( espaço do mundo ), depois 50 graus ao redorX
( espaço do mundo ) e depois 50 graus ao redorZ
( espaço do mundo ).Fornecerei minha solução como resposta até que alguém possa explicar por que isso funciona.
A cada renderização eu estava reconstruindo meu quaternion usando os ângulos armazenados no meu vetor de rotação e depois aplicando o quaternion à minha transformação final.
No entanto, para mantê-lo em todos os eixos do mundo, tive que reter o quaternion em todos os quadros e girar apenas objetos usando uma diferença de ângulo, ou seja.
(Detalhado para facilitar a leitura)
Acho que dsilva.vinicius estava tentando chegar a esse ponto.
fonte
Você precisará armazenar a ordem das rotações.
Armazene sua matriz de rotação atual e pré-multiplique cada rotação à medida que elas surgirem.
fonte
Além da resposta ao @ concept3d, você pode usar 3 matrizes de rotação extrínseca para girar em torno do eixo nas coordenadas do mundo. Citando da Wikipedia :
Portanto, o que você precisa é inverter a ordem das rotações em relação ao que você faria usando rotações intrínsecas (ou no espaço local). O @Syntac pediu uma rotação zxy, então devemos fazer uma rotação extrínseca yxz para obter o mesmo resultado. O código está abaixo:
A matriz valoriza a explicação aqui .
Esse código é didático, não ideal, pois você pode reutilizar várias matrizes D3DXMATRIX.
fonte