Depois de tanta leitura sobre transformações, é hora de implementar um trackball para o meu aplicativo. Entendo que preciso criar um vetor da origem para onde o mouse é clicado e depois outro da origem para onde o mouse é liberado.
Minha pergunta é: eu tenho que transformar as cordas de pixel (x, y) em cordas do mundo ou devo fazer tudo no espaço da imagem (considerando o espaço da imagem, a projeção 2D da cena é medida em pixels)?
EDITAR
A resposta de Richie Sams é muito boa. No entanto, acho que estou seguindo uma abordagem um pouco diferente. Por favor, corrija-me se estiver errado ou se estiver entendendo algo errado.
Na minha aplicação eu tenho uma SimplePerspectiveCamera
classe que recebe a position
da câmera, o position of the target
que estamos olhando, o up
vetor, o fovy
, aspectRatio
, near
e far
distâncias.
Com eles, construo minhas matrizes de exibição e projeção. Agora, se eu quiser aumentar / diminuir o zoom, atualizo o campo de visão e atualizo minha matriz de projeção. Se eu quiser fazer uma panorâmica, movo a posição da câmera e observo o delta que o mouse produz.
Finalmente, para rotações, posso usar transformação de eixo angular ou quaterniões. Para isso, salvei as cordas de pixel onde o mouse foi pressionado e, quando o mouse se move, também salvei as cordas de pixel.
Para cada par de coords I pode calcular o valor de Z determinado a fórmula para uma esfera, ou seja, sqrt (1-x ^ 2-y ^ 2), em seguida, calcular a vectores que vão desde o target
de PointMousePressed
e a partir target
de PointMouseMoved
, fazer produto cruzado para obter o eixo de rotação e usar qualquer método para calcular a nova posição da câmera.
No entanto, minha maior dúvida é que os valores (x, y, z) são dados em cordas de pixel e, ao calcular os vetores que estou usando, target
esse é um ponto nas cordas do mundo. Essa mistura de sistema de coordenadas não está afetando o resultado da rotação que estou tentando fazer?
z
valor de uma esfera de raior
, no entanto, não tenho certeza se essa esfera vive no espaço do mundo ou no espaço da imagem e quais são as implicações. Talvez eu esteja pensando demais no problema.Respostas:
Supondo que você queira dizer uma câmera que gira com base no movimento do mouse:
Uma maneira de implementá-lo é acompanhar a posição da câmera e sua rotação no espaço. As coordenadas esféricas são convenientes para isso, pois você pode representar os ângulos diretamente.
A câmera está localizada em P, definida por m_theta, m_phi e m_radius. Podemos girar e mover-nos livremente para onde quisermos, alterando esses três valores. No entanto, sempre olhamos e giramos em torno de m_target. m_target é a origem local da esfera. No entanto, somos livres para mudar essa origem para onde quisermos no espaço do mundo.
Existem três funções principais da câmera:
Em suas formas mais simples, Rotate () e Zoom () são triviais. Basta modificar m_theta, m_phi e m_radius, respectivamente:
O movimento panorâmico é um pouco mais complicado. Um pan da câmera é definido como mover a câmera para a esquerda / direita e / ou para cima / para baixo, respectivamente, para a visualização atual da câmera. A maneira mais fácil de conseguir isso é converter nossa visão atual da câmera de coordenadas esféricas em coordenadas cartesianas. Isso nos dará um up e certos vetores.
Então, primeiro, convertemos nosso sistema de coordenadas esféricas em cartesiano para obter nosso vetor de aparência . Em seguida, fazemos o produto cruzado do vetor com o mundo até vetor, a fim de obter um certo vetor. Este é um vetor que aponta diretamente para a direita da visualização da câmera. Por fim, fazemos outro produto cruzado de vetor para obter a câmera de vetor.
Para finalizar o pan, movemos m_target pelos vetores para cima e para a direita .
Uma pergunta que você pode estar perguntando é: Por que converter entre cartesiano e esférico o tempo todo (você também precisará converter para criar a matriz View).
Boa pergunta. Eu também tive essa pergunta e tentei usar exclusivamente cartesiano. Você acaba com problemas com rotações. Como as operações de ponto flutuante não são exatamente precisas, várias rotações acabam acumulando erros, que correspondiam à câmera lenta e involuntariamente.
Então, no final, eu fiquei com coordenadas esféricas. A fim de combater os cálculos extras, acabei armazenando em cache a matriz de visualização e só a calculo quando a câmera se move.
O último passo é usar esta classe de câmera. Basta chamar a função de membro apropriada nas funções MouseDown / Up / Scroll do seu aplicativo:
As variáveis m_camera * Factor são apenas fatores de escala que alteram a rapidez com que sua câmera gira / desloca / rola
O código que eu tenho acima é uma versão pseudo-código simplificado do sistema de câmera que eu fiz para um projeto paralelo: camera.h e camera.cpp . A câmera tenta imitar o sistema de câmera Maya. O código é gratuito e de código aberto, portanto, fique à vontade para usá-lo em seu próprio projeto.
fonte
Caso você queira dar uma olhada em uma solução pronta, eu tenho uma porta de THREE.JS TrackBall controla em C ++ e C #
fonte