已解决
我正在制作一个引擎中的3D传送门系统(类似于Portal游戏)。每个传送门都有其保存在四元数中的自身方向。为了在其中一个传送门中呈现虚拟场景,我需要计算两个四元数之间的差异,并将结果用于旋转虚拟场景。
当在左墙上创建第一个传送门和右墙上创建第二个传送门时,从一个传送门到另一个传送门的旋转将只在一个轴上进行,但例如当第一个传送门创建在地板上,而第二个传送门创建在右墙上时,从一个传送门到另一个传送门的旋转可能涉及两个轴,这就是问题所在,因为旋转出错了。
我认为问题存在是因为例如 X
轴和 Z
轴的方向被一起存储在一个四元数中,而我需要它们分别来手动相乘 X
* Z
(或 Z
* X
),但如何使用一个四元数(即差异四元数)进行操作?还是有其他方法可以正确旋转场景吗?
编辑:
这张图片展示了两个传送门P1和P2,箭头显示它们的旋转方向。当我看进入P1时,我将看到P2所看到的内容。为了找到所需的旋转,使主场景与此图中的虚拟场景相同,我正在执行以下操作:
- 获取四元数P2到四元数P1的差异
- 在Y轴(传送门的上方)上将结果旋转180度
- 使用结果旋转虚拟场景
以上方法仅在差异发生在一个轴上时有效。当一个传送门位于地板或天花板上时,这种方法将不起作用,因为差异四元数是在多个轴上构建的。如建议的那样,我尝试将P1的四元数乘以P2的四元数,并颠倒顺序,但这并没有奏效。
编辑2:
为了找到从P2到P1的差异,我正在执行以下操作:
Quat q1 = P1->getOrientation();
Quat q2 = P2->getOrientation();
Quat diff = Quat::diff(q2, q1); // q2 * diff = q1 //
这里是Quat::diff函数:
GE::Quat GE::Quat::diff(const Quat &a, const Quat &b)
{
Quat inv = a;
inv.inverse();
return inv * b;
}
逆元:
void GE::Quat::inverse()
{
Quat q = (*this);
q.conjugate();
(*this) = q / Quat::dot((*this), (*this));
}
变位:
void GE::Quat::conjugate()
{
Quat q;
q.x = -this->x;
q.y = -this->y;
q.z = -this->z;
q.w = this->w;
(*this) = q;
}
点积:
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;
}
操作符*:
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;
}
操作符/:
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);
}
所有这些东西都是有效的,因为我已经使用GLM库进行了测试