[使用OpenGL使用鼠标旋转立方体

问题描述 投票:0回答:1

我正在使用OpenGL和GLUT来显示多维数据集。现在,我希望能够通过在窗口上拖动鼠标来围绕立方体旋转摄像机。当鼠标水平移动时,多维数据集应绕其垂直轴旋转,当鼠标垂直移动时,多维数据集应绕其水平轴旋转,二者均以固定距离d进行。

[为了实现这一点,我尝试用球坐标thetaphi表示相机。当鼠标在屏幕上水平移动时,我增大(右)或减小(左)theta,而当鼠标垂直移动时,我增大(上)或减小(下)phi。然后,我使用以下方程式确定相机和相关视图矩阵的笛卡尔位置:

float eye_x = d * sin(phi) * cos(theta);
float eye_y = d  * sin(phi) * sin(theta);
float eye_z = d  * cos(phi);
glm::vec3 centre(0.0f, 0.0f, 0.0f);
glm::vec3 up(0, 1, 0);
view_matrix = glm::lookAt(eye, centre, up);

当我运行此代码时,当我在窗口上移动鼠标时,立方体会旋转,但不会以我期望的方式旋转。另外,立方体似乎在某些点突然“翻转”其方向。

有人可以为我指出正确的方向,我应该如何正确实施此方法?

c++ opengl glut glm-math
1个回答
2
投票

您提到的不连续性,即“翻转”,是由于在lookat矩阵构造中使用了固定的“向上”方向而产生的。如果“眼睛”方向为“向上”方向,则lookat矩阵的行为会异常。因此,您的代码将需要直接调整“向上”。

但是,基本问题是它没有按照您希望的方式旋转?这是因为使用了错误的工具来解决问题,也由于缺乏对问题本身的全面了解。

我假设您要在Maya或Blender3D等3D建模应用程序中实现类似鼠标旋转控件的功能。如果您注意的话,您会注意到viewer的方向实际上是由此类鼠标控件考虑在内的。如果您更改查看对象的角度,则应用于该对象的旋转将发生变化。

或者换句话说,您想要控制对象相对于相机的方向。但是,您最终要设置的矩阵是相对于world

的旋转。

所以这就是你要做的。您需要根据鼠标移动生成方向偏移。这是相对于相机而言的。然后,您需要将该方向偏移转换为相对于世界的偏移。然后,将其应用于对象的当前方向。

球面坐标不能执行此操作。它们以相对于世界的角度进行交易。并且即使不是不可能,变换这样的角度也是困难的。相反,您需要使用方向[[直接,而不是角度。

这意味着矩阵或四元数。

我编写的非官方GL SDK的class that does this。关键代码是:

void ObjectPole::RotateViewDegrees( const glm::fquat &rot, bool bFromInitial ) { if(!m_bIsDragging) bFromInitial = false; if(m_pView) { glm::fquat viewQuat = glm::quat_cast(m_pView->CalcMatrix()); glm::fquat invViewQuat = glm::conjugate(viewQuat); m_po.orientation = glm::normalize((invViewQuat * rot * viewQuat) * (bFromInitial ? m_startDragOrient : m_po.orientation)); } else RotateWorldDegrees(rot, bFromInitial); } 函数的输入是表示旋转度的四元数,其基于鼠标在帧之间移动了多少而计算出。该函数的工作是将该增量应用于对象的当前方向。但是,增量位于相机空间(用户正在查看的空间)中。由于存储的对象的方向位于世界空间中,因此需要在将增量应用于对象的方向之前将其转换为世界空间。

这是invViewQuat * rot * viewQuat的工作。数学起作用的原因是a bit complex
© www.soinside.com 2019 - 2024. All rights reserved.