绕着错误的轴旋转
Rotating around the wrong axis
我正在尝试围绕 space 中的一个点旋转相机,如下所示:
红点通常是某个物体的中心。
用户可以用鼠标旋转相机,其中垂直移动应垂直旋转(x 轴),水平移动应水平旋转(y 轴)。
我想要的
对 y 轴的旋转始终是表观 相机的 y 轴,与 x 轴相同。例如,如果用户向上移动鼠标,它应该总是看起来像你在向上移动并越过相机聚焦的对象。如果用户从左向右移动鼠标,它应该看起来像对象在它的 y 轴上旋转(或者相机在它的 y 轴上移动)。
因此,如果用户将鼠标向左移动一点,然后开始向上移动,从新的角度来看,它们看起来应该仍然越过对象的顶部,而不是旋转一个角度沿着世界的实际 x 轴。
例如,这似乎是我使用过的大多数 3D 软件的标准配置。
我试过的
在这里有很多问题的帮助下,我已经非常接近我想要的,但又不完全是。
对于以下代码:view_
是 4x4 视图矩阵,origin_
是我们旋转的图片中的点,position_
是蓝线在表示相机距离原点(或任何相机平移,但尚未实现)有多远的图像中,pitch
、yaw
和 roll
是数量我们想要旋转(在这种情况下,roll 始终为零)。
到目前为止,我最好的成绩是:
// rotation_ is a vec3 here
rotation_ += glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll) );
glm::mat4 rot = glm::rotate( glm::mat4(1.0f), rotation_.x, glm::vec3(1.0f, 0.0f, 0.0f) );
rot = glm::rotate( rot, rotation_.y, glm::vec3(0.0f, 1.0f, 0.0f) );
rot = glm::rotate( rot, rotation_.z, glm::vec3(0.0f, 0.0f, 1.0f) );
view_ = glm::translate(glm::translate( glm::mat4(1.0f), position_ ) * rot, origin_);
关闭,但沿 x 轴旋转约 90 度会导致围绕 y 轴的进一步旋转 出现 围绕 z 轴。不过,我似乎无法用 y 轴到 x 轴复制它,所以我很好奇这是否真的是万向节锁或其他东西。
为了解决这个问题,我尝试将 rotation_
存储为四元数,并像这样进行旋转:
// rotation_ is a quaternion here.
rotation_ *= glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll)));
glm::vec3(1.0f, 0.0f, 0.0f) );
view_ = glm::translate(glm::translate( glm::mat4(1.0f), position_ ) * rot, origin_);
这实际上更糟。看起来我总是沿着世界的轴旋转而不是相机的方向,这不是我想要的。
如何让相机在移动鼠标时总是看起来像垂直旋转up/down,总是看起来它在移动时水平旋转 left/right?
我组合四元数的顺序错了!
// rotation_ is a quaternion here.
rotation_ *= glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll)));
glm::vec3(1.0f, 0.0f, 0.0f) );
view_ = glm::translate(glm::translate( glm::mat4(1.0f), position_ ) * rot, origin_);
行
rotation_ *= glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll)));
应该是
rotation_ = glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll))) * rotation_;
像这样,四元数解决方案就像我预期的那样工作。
如果我没有理解错的话,这是因为我想先旋转到新的增量旋转,然后再将旧的旋转添加到其中。这让我可以先将新的旋转应用于相机的轴,然后再考虑其余的旋转。
如果反过来,它会旋转到旧旋转,然后将新旋转添加到旧旋转,这会导致新旋转未按我预期的方向应用。
我正在尝试围绕 space 中的一个点旋转相机,如下所示:
红点通常是某个物体的中心。
用户可以用鼠标旋转相机,其中垂直移动应垂直旋转(x 轴),水平移动应水平旋转(y 轴)。
我想要的
对 y 轴的旋转始终是表观 相机的 y 轴,与 x 轴相同。例如,如果用户向上移动鼠标,它应该总是看起来像你在向上移动并越过相机聚焦的对象。如果用户从左向右移动鼠标,它应该看起来像对象在它的 y 轴上旋转(或者相机在它的 y 轴上移动)。
因此,如果用户将鼠标向左移动一点,然后开始向上移动,从新的角度来看,它们看起来应该仍然越过对象的顶部,而不是旋转一个角度沿着世界的实际 x 轴。
例如,这似乎是我使用过的大多数 3D 软件的标准配置。
我试过的
在这里有很多问题的帮助下,我已经非常接近我想要的,但又不完全是。
对于以下代码:view_
是 4x4 视图矩阵,origin_
是我们旋转的图片中的点,position_
是蓝线在表示相机距离原点(或任何相机平移,但尚未实现)有多远的图像中,pitch
、yaw
和 roll
是数量我们想要旋转(在这种情况下,roll 始终为零)。
到目前为止,我最好的成绩是:
// rotation_ is a vec3 here
rotation_ += glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll) );
glm::mat4 rot = glm::rotate( glm::mat4(1.0f), rotation_.x, glm::vec3(1.0f, 0.0f, 0.0f) );
rot = glm::rotate( rot, rotation_.y, glm::vec3(0.0f, 1.0f, 0.0f) );
rot = glm::rotate( rot, rotation_.z, glm::vec3(0.0f, 0.0f, 1.0f) );
view_ = glm::translate(glm::translate( glm::mat4(1.0f), position_ ) * rot, origin_);
关闭,但沿 x 轴旋转约 90 度会导致围绕 y 轴的进一步旋转 出现 围绕 z 轴。不过,我似乎无法用 y 轴到 x 轴复制它,所以我很好奇这是否真的是万向节锁或其他东西。
为了解决这个问题,我尝试将 rotation_
存储为四元数,并像这样进行旋转:
// rotation_ is a quaternion here.
rotation_ *= glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll)));
glm::vec3(1.0f, 0.0f, 0.0f) );
view_ = glm::translate(glm::translate( glm::mat4(1.0f), position_ ) * rot, origin_);
这实际上更糟。看起来我总是沿着世界的轴旋转而不是相机的方向,这不是我想要的。
如何让相机在移动鼠标时总是看起来像垂直旋转up/down,总是看起来它在移动时水平旋转 left/right?
我组合四元数的顺序错了!
// rotation_ is a quaternion here.
rotation_ *= glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll)));
glm::vec3(1.0f, 0.0f, 0.0f) );
view_ = glm::translate(glm::translate( glm::mat4(1.0f), position_ ) * rot, origin_);
行
rotation_ *= glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll)));
应该是
rotation_ = glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll))) * rotation_;
像这样,四元数解决方案就像我预期的那样工作。
如果我没有理解错的话,这是因为我想先旋转到新的增量旋转,然后再将旧的旋转添加到其中。这让我可以先将新的旋转应用于相机的轴,然后再考虑其余的旋转。
如果反过来,它会旋转到旧旋转,然后将新旋转添加到旧旋转,这会导致新旋转未按我预期的方向应用。