Estou codificando um mecânico que permite que um usuário se mova pela superfície de uma esfera. A posição na esfera está atualmente armazenada como theta
e phi
, onde theta
é o ângulo entre o eixo z e a projeção xz da posição atual (ou seja, rotação em torno do eixo y) e phi
é o ângulo do eixo y para a posição. Eu expliquei isso mal, mas é essencialmente theta = yaw
,phi = pitch
Vector3 position = new Vector3(0,0,1);
position.X = (float)Math.Sin(phi) * (float)Math.Sin(theta);
position.Y = (float)Math.Sin(phi) * (float)Math.Cos(theta);
position.Z = (float)Math.Cos(phi);
position *= r;
Acredito que isso seja preciso, mas posso estar errado. Eu preciso ser capaz de me mover em uma direção pseudo-bidimensional arbitrária em torno da superfície de uma esfera na origem do espaço do mundo com raio r
. Por exemplo, segurar Wdeve se mover pela esfera em uma direção para cima em relação à orientação do jogador.
Acredito que deveria usar um Quaternion para representar a posição / orientação na esfera, mas não consigo pensar na maneira correta de fazê-lo. Geometria esférica não é meu ponto forte.
Essencialmente, preciso preencher o seguinte bloco:
public void Move(Direction dir)
{
switch (dir)
{
case Direction.Left:
// update quaternion to rotate left
break;
case Direction.Right:
// update quaternion to rotate right
break;
case Direction.Up:
// update quaternion to rotate upward
break;
case Direction.Down:
// update quaternion to rotate downward
break;
}
}
(1,1,1)
exploração deixou giraria em torno da esfera, passando(~1.2,0,~-1.2)
, em seguida(-1,-1,-1)
, em seguida,(~-1.2,0,~1.2)
e de volta para(1,1,1)
.theta
e àphi
medida que sua posição é atualizada, você está tornando seu problema desnecessariamente complexo. Muito mais fácil calcular simplesmente os 2 eixos de rotação de cada quadro (um dos quais (guinada) nunca muda) eVector3.Transorm
ao redor da esfera. Isso simplificaria seu problema, mas fará com que você se desconecte comphi
&theta
.Respostas:
Na verdade, acontece que você não pode ter 'os dois lados': se sua intenção é não ter nenhum senso de 'orientação absoluta' na esfera (isto é, se os jogadores nem sempre estão, por exemplo, olhando para os polos) ), você precisará ter uma noção da orientação do jogador. Isso ocorre porque, ao contrário do que a intuição pode sugerir, o movimento na esfera não é exatamente como o movimento de um avião, nem mesmo localmente (bastante); a curvatura intrínseca da esfera significa que os jogadores podem realizar ações que se revezarão!
Para o exemplo mais extremo do que estou falando, imagine que o jogador comece em um ponto do equador (por conveniência, imaginemos um mostrador de relógio mapeado no equador de cima e coloque o jogador às 6 horas ), voltado para cima, isto é, em direção ao Polo Norte. Suponha que o jogador caminhe até o Polo Norte; então eles estarão voltados diretamente para o ponto das 12 horas. Agora, deixe o jogador se mover diretamente para a direita, do Polo Norte de volta ao Equador; eles acabam no ponto das 3 horas - mas porque o rosto deles não muda quando se movem para a direita(a ideia é que o rosto deles não mude, não importa como eles se movam), eles ainda estarão enfrentando o ponto das 12 horas - agora estão enfrentando ao longo do equador! Agora, deixe-os recuar 'para trás' até o ponto inicial (6 horas); então eles ainda estarão de frente para o equador, de modo que estarão voltados para o ponto das 3 horas - apenas mover-se ao longo da esfera sem nunca mudar sua orientação 'pessoal' os fez girar de frente para o pólo norte para de frente para o equador! De certa forma, essa é uma elaboração da velha piada 'um caçador se move uma milha ao sul, uma milha a oeste e depois uma milha ao norte' - mas aqui estamos aproveitando a curvatura da esfera para efetuar uma mudança de direção. Observe que o mesmo efeito ainda acontece mesmo em escalas muito menores;
Felizmente, os quaternions (como você se notou) lidam com essa situação; Uma vez que um quaternion representa uma rotação arbitrária, ele efetivamente representa um 'ponto mais orientação' arbitrário na esfera: imagine começar com um 'triaxis' na origem e dar-lhe alguma rotação arbitrária, movendo uma unidade na direção que os eixos girados ' Pontos do eixo Z; um pouco de reflexão o convencerá de que isso o levará a um ponto na esfera unitária com alguma 'orientação' (ou seja, algum arranjo dos eixos X e Y da sua triaxis) e que você poderá chegar a todos os pontos + orientação na unidade esfera desta maneira (apenas atribua seu eixo Z para apontar ao longo da linha desde a origem até o ponto na esfera, depois transporte seus triaxes de volta para a origem ao longo dessa linha). O que mais, Como a multiplicação de quaternions corresponde à composição das rotações, cada uma das operações que você descreve pode ser representada multiplicando sua 'orientação atual' por um quaternion escolhido adequadamente: especificamente, desde o quaternion (unit) (qx, qy, qz, qw) significa 'girar em torno do eixo (qx, qy, qz) por arccos (qw)' e, em seguida (dependendo da sua escolha específica do sistema de coordenadas, e deixar c_a ser cos (alfa) e s_a ser sin (alfa)) dois dos três quaternions M_x = (s_a, 0, 0, c_a), M_y = (0, s_a, 0, c_a) e M_z = (0, 0, s_a, c_a) representarão 'rotate (ie move) na direção I atualmente estou enfrentando por alfa 'e' giro em uma direção ortogonal à que estou enfrentando atualmente por alfa '. (O terceiro desses quaternions representará 'rodar meu personagem em torno de seu próprio eixo'
Cur_q = M_x * Cur_q
se o jogador pressionou ouCur_q = M_y * Cur_q
se pressionou para a direita (ou possivelmente algo comoCur_q = M_yinv * Cur_q
se o jogador pressionou para a esquerda, onde M_yinv é o 'inverso' do quaternion M_y, representando uma rotação para o outro lado). Observe que você deve ter cuidado em qual 'lado' você aplica a rotação, seja para pré-multiplicar ou pós-multiplicar; para ser franco, pode ser mais fácil resolver isso com tentativa e erro, tentando ambas as multiplicações e vendo o que funciona.Ir de seu quaternion atualizado a um ponto na esfera (e a uma orientação de seu personagem) também é relativamente direto: pela correspondência do último parágrafo, tudo o que você precisa fazer é usar seu quaternion nos vetores básicos (1, 0,0), (0,1,0) e (0,0,1) do seu quadro através da operação 'girar vetor por quaternião' v → qvq -1 (onde as multiplicações aqui são quaternárias se multiplica e identificamos o vetor v = (x, y, z) com o 'quaternion degenerado' (x, y, z, 0)). Por exemplo, a posição na esfera unitária é obtida apenas pela transformação do vetor z: pos = (qx, qy, qz, qw) * (0, 0, 1, 0) * (-qx, -qy, -qz, qw) = (qx, qy, qz, qw) * (qy, -qx, qw, qz) = (2 (qy * qw + qz * qx), 2 (qz * qy-qw * qx), (qz ^ 2 + qw ^ 2) - (qx ^ 2 + qy ^ 2), 0), então
(2(qy*qw+qz*qx), 2(qz*qy-qw*qx), (qz^2+qw^2)-(qx^2+qy^2))
seriam as coordenadas do usuário 'transformado' na esfera unitária (e, para obter as coordenadas em uma esfera arbitrária, é claro, você apenas as multiplicaria pelo raio da esfera); cálculos semelhantes funcionam para os outros eixos, para definir, por exemplo, a direção do usuário.fonte
Move()
procedimento, mas para obter o eixo normalizado (ou seja, minha posição), eu apenas aceitaria(sin(qx),sin(qy),sin(qw)) * r
?Eu acho que você deseja algo semelhante a este http://www.youtube.com/watch?v=L2YRZbRSD1k
Eu desenvolvi isso para um jogo de 48 horas ... você pode baixar o código aqui ... http://archive.globalgamejam.org/2011/evil-god
Usei algo semelhante ao seu código para obter as cordas 3D ... mas girei o planeta e o jogador estava na mesma posição, acho que você está interessado no movimento da criatura, é o seguinte:
fonte