解决了
我正在我的引擎中制作一个 3D 门户系统(如 Portal 游戏)。每个门户都有自己的方向保存在一个四元数中。要在其中一个门户中渲染虚拟场景,我需要计算两个四元数之间的差异,并将结果用于旋转虚拟场景。
在左墙上创建第一个门户,在右墙上创建第二个时,从一个到另一个的旋转将仅在一个轴上发生,但例如当第一个门户将在地板上创建时,第二个在右墙上,从一个到另一个的旋转可能在两个轴上,这就是问题所在,因为旋转出错了。
我认为问题的存在是因为例如X
轴和Z
轴的方向一起存储在一个四元数中,我需要单独手动乘以X
* Z
(或Z
* X
),但是如何只使用一个四元数(差异四元数)?还是有其他方法来纠正旋转场景?
编辑:
这张图片上有两个门户 P1 和 P2,箭头显示它们是如何旋转的。当我查看 P1 时,我会看到 P2 中的内容。为了找到我需要旋转主场景的旋转,就像这张图片中的虚拟场景一样,我正在执行以下操作:
- 从四元数 P2 到四元数 P1
- Y 轴旋转 180 度的结果(传送门的 UP)
- 使用结果旋转虚拟场景
仅当差异仅发生在一个轴上时,上述方法才有效。当一个门户将在地板上或天花板上时,这将不起作用,因为差异四元数构建在多个轴上。正如建议的那样,我尝试将 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库对其进行了测试