O que você está pedindo é chamado rotação de Arcball. Quaternions são a solução fácil somente se você entender como eles funcionam. Você pode conseguir o mesmo sem quaternions.
Pré-requisitos
Você sabe como girar objetos em geral? Digamos que você tenha um objeto na origem. Você sabe como você o gira (dica: multiplique por alguma matriz de rotação)? Se sim, suponho que você saiba o que acontecerá se você traduzir o objeto primeiro e depois girá-lo?
Você deve saber como calcular uma matriz de rotação a partir do eixo angular (fácil como torta, veja a infinidade de equações on-line, muitas delas fornecem o código também)
Solução
- Obter da câmera para cima e certos vetores. Observe que eles devem ser normalizados.
- Obtenha o vetor do ponto de foco para a câmera (camPosition - Focus). Este é o vetor que você vai girar. Vamos chamar isso de camFocusVector .
- Decida quanto você deseja girar em guinada / inclinação em relação à câmera
- Crie duas matrizes de rotação. A primeira matriz de rotação utilizará a parte superior da câmera como o eixo e o ângulo de guinada que você decidiu. A segunda matriz de rotação usará o lado direito da câmera como o eixo e o ângulo de inclinação que você decidiu.
- Agora gire o camFocusVector com as novas matrizes de rotação. Esta é agora a sua nova posição da câmera em relação à origem. É claro que queremos que seja relativo ao ponto de foco ...
- Adicione a posição do ponto de foco ao camFocusVector . Esta é agora a nova posição da sua câmera. Traduza sua câmera adequadamente.
- Por fim, peça à câmera que foque no ponto de foco chamando sua função lookAt ()
Ressalvas
Você terá que procurar certos casos ou singularidades nas quais sua câmera irá parar de funcionar. Olhando para baixo / para cima, por exemplo. Vou deixar você descobrir como lidar com isso.
EDIT1: Como recalcular os vetores ortonormais da câmera
Você já sabe a direção da câmera ((cameraPos - focusPoint) .normalize ()). Agora suponha que a câmera esteja acima de + Y (ou seja, o eixo superior atual do seu mundo é ... depende de você). Agora simplesmente cruze a direção com a seta para cima para acertar . Feito? Não! Seu vetor ativo não é mais ortogonal aos outros dois. Para corrigir isso, cruz direita com direção e você obter o seu novo -se .
Observe que o Gram-Schmidt é realmente o que deve ser usado para ortonormalizar vetores.
Novamente, tome nota das advertências, pois isso não funcionará em alguns casos (a direção é paralela à alta, por exemplo).