solvable
I create a 3D portal system in my engine (for example, a game in Portal). Each of the portals has its own orientation stored in the quaternion. To display a virtual scene in one of the portals, I need to calculate the difference between the two quaternions, and use the result to rotate the virtual scene.
When creating the first portal on the left wall and the second on the right wall, the rotation from one to the other will occur only on one axis, but, for example, when the first portal is created on the floor and the second on the right wall, rotation from one to the other can be two axes, and this problem, because the rotation goes wrong.
I think the problem exists because the orientation, for example the X axis and the Z axis, are stored together in the same quaternion, and I need this separately for manual multiplication of X * Z (or Z * X ), but how to do this with only one quaternion (difference quaternion)? Or is there another way to fix the rotation of the scene?
EDIT:
Here, in this figure, there are two ports P1 and P2, the arrows show how they rotate. When I look at P1, I will see what P2 is seeing. To find the rotation that I need to rotate the main scene to be like a virtual scene in this shot, I do the following:
- Getting the difference from Quaternion P2 to Quaternion P1
- 180 Degree Rotating Y-axis (UP Portal)
- Using the result to rotate a virtual scene
This method above only works when the difference occurs with only one axis. When one portal is on the floor or on the ceiling, this will not work, because the difference quaternion is built on more than one axis. As suggested, I tried to multiply the quaternion P1 by the quaternion P2 and vice versa, but this does not work.

EDIT 2:
To find the difference from P2 to P1, I do the following:
Quat q1 = P1->getOrientation(); Quat q2 = P2->getOrientation(); Quat diff = Quat::diff(q2, q1);
Here's the Quat :: diff function:
GE::Quat GE::Quat::diff(const Quat &a, const Quat &b) { Quat inv = a; inv.inverse(); return inv * b; }
Inverse:
void GE::Quat::inverse() { Quat q = (*this); q.conjugate(); (*this) = q / Quat::dot((*this), (*this)); }
Paired:
void GE::Quat::conjugate() { Quat q; qx = -this->x; qy = -this->y; qz = -this->z; qw = this->w; (*this) = q; }
Spot product:
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; }
Operator *:
const GE::Quat GE::Quat::operator* ( const Quat &q) const { Quat qu; qu.x = this->w*qx + this->x*qw + this->y*qz - this->z*qy; qu.y = this->w*qy + this->y*qw + this->z*qx - this->x*qz; qu.z = this->w*qz + this->z*qw + this->x*qy - this->y*qx; qu.w = this->w*qw - this->x*qx - this->y*qy - this->z*qz; return qu; }
Operator/:
const GE::Quat GE::Quat::operator/ (float s) const { Quat q = (*this); return Quat(qx / s, qy / s, qz / s, qw / s); }
All this works because I tested it with the GLM library