Diferença entre os dois quaternions

Resolvido

Estou criando um sistema de portal 3D no meu mecanismo (como o jogo do Portal). Cada um dos portais tem sua própria orientação salva em um quaternion. Para renderizar a cena virtual em um dos portais, preciso calcular a diferença entre os dois quaternions e o resultado usado para girar a cena virtual.

Ao criar o primeiro portal na parede esquerda e o segundo na parede direita, a rotação de um para o outro ocorrerá em apenas um eixo, mas, por exemplo, quando o primeiro portal será criado no piso e o segundo na parede direita, a rotação de um para outro pode estar em dois eixos, e esse é o problema, porque a rotação dá errado.

Eu acho que o problema existe porque a orientação, por exemploX eixo eZ eixo são armazenados juntos em um quaternion e eu preciso dele separadamente para multiplicar manualmenteX * Z (ouZ * X), mas como fazer isso com apenas um quaternion (o quaternion da diferença)? Ou existe outra maneira de corrigir a rotação da cena?

EDITAR:

Aqui nesta figura há dois portais P1 e P2, as setas mostram como eles são rotacionados. Enquanto olho para P1, verei o que vê P2. Para encontrar a rotação que eu preciso girar a cena principal para ser como a cena virtual nesta imagem, estou fazendo o seguinte:

Obtendo a diferença do quaternion P2 para o quaternion P1Resultado de rotação de 180 graus no eixo Y (UP do portal)Usando o resultado para girar a cena virtual

Este método acima funciona apenas quando a diferença ocorre em apenas um eixo. Quando um portal estiver no chão ou no teto, isso não funcionará porque o quaternion da diferença é construído em mais de um eixo. Conforme sugerido, tentei multiplicar o quaternion de P1 pelo quaternion de P2, e inversamente, mas isso não está funcionando.

EDIT 2:

Para encontrar a diferença de P2 para P1, estou fazendo o seguinte:

Quat q1 = P1->getOrientation();
Quat q2 = P2->getOrientation();

Quat diff = Quat::diff(q2, q1);  // q2 * diff = q1 //

Aqui está a função Quat :: diff:

GE::Quat GE::Quat::diff(const Quat &a, const Quat &b)
{
    Quat inv = a;
    inv.inverse();
    return inv * b;
}

Inverso:

void GE::Quat::inverse()
{
    Quat q = (*this);
    q.conjugate();
    (*this) = q / Quat::dot((*this), (*this));
}

Conjugado:

void GE::Quat::conjugate()
{
    Quat q;
    q.x = -this->x;
    q.y = -this->y;
    q.z = -this->z;
    q.w = this->w;

    (*this) = q;
}

Produto de ponto:

float GE::Quat::dot(const Quat &q1, const Quat &q2)
{
    return q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;
}

Operador*:

const GE::Quat GE::Quat::operator* ( const Quat &q) const
{
    Quat qu;
    qu.x = this->w*q.x + this->x*q.w + this->y*q.z - this->z*q.y;
    qu.y = this->w*q.y + this->y*q.w + this->z*q.x - this->x*q.z;
    qu.z = this->w*q.z + this->z*q.w + this->x*q.y - this->y*q.x;
    qu.w = this->w*q.w - this->x*q.x - this->y*q.y - this->z*q.z;
    return qu;
}

Operador/:

const GE::Quat GE::Quat::operator/ (float s) const
{
    Quat q = (*this);
    return Quat(q.x / s, q.y / s, q.z / s, q.w / s);
}

Tudo isso funciona, porque eu testei comGLM biblioteca

questionAnswers(5)

yourAnswerToTheQuestion