Diferencia entre los dos cuaterniones.

Resuelto

Estoy haciendo un sistema de portal 3D en mi motor (como el juego Portal). Cada uno de los portales tiene su propia orientación guardada en un cuaternión. Para renderizar la escena virtual en uno de los portales, necesito calcular la diferencia entre los dos cuaterniones, y el resultado se usa para rotar la escena virtual.

Al crear el primer portal en la pared izquierda, y el segundo en la pared derecha, la rotación de uno a otro tendrá lugar en un solo eje, pero, por ejemplo, cuando se creará el primer portal en el piso y el segundo en la pared derecha, la rotación de uno a otro podría estar en dos ejes, y ese es el problema, porque la rotación sale mal.

Creo que el problema existe porque la orientación, por ejemploX eje yZ eje se almacenan juntos en un cuaternión y lo necesito por separado para multiplicar manualmenteX * Z (oZ * X), pero ¿cómo hacerlo con un solo quaternion (la diferencia quaternion)? ¿O hay otra forma de corregir la rotación de la escena?

EDITAR:

Aquí en esta imagen hay dos portales P1 y P2, las flechas muestran cómo se rotan. Mientras estoy mirando a P1, veré lo que ve a P2. Para encontrar la rotación que necesito para girar la escena principal para que sea como la escena virtual en esta imagen, estoy haciendo lo siguiente:

Obteniendo la diferencia de quaternion P2 a quaternion P1Resultado giratorio 180 grados en el eje Y (portal hacia ARRIBA)Usando el resultado para rotar la escena virtual

Este método anterior solo funciona cuando la diferencia tiene lugar en un solo eje. Cuando un portal estará en el piso o en el techo, esto no funcionará porque la diferencia del cuaternión se construye en más de un eje. Como sugerí, intenté multiplicar el cuaternión de P1 por el cuaternión de P2, e inversamente, pero esto no funciona.

EDITAR 2:

Para encontrar la diferencia de P2 a P1, estoy haciendo lo siguiente:

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

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

Aquí está la función 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;
}

Producto de punto:

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);
}

Todo esto funciona, porque lo he probado conGLM biblioteca

Respuestas a la pregunta(5)

Su respuesta a la pregunta