我正在尝试实现一个opengl相机,它可以围绕指定的世界坐标旋转相机的位置。我正在尝试使用glm数学库;我的代码如下
void Camera::dolly(double angle_x, double angle_y, const double& loc_x, const double& loc_y, const double& loc_z, const double& dt) {
glm::vec3 target = glm::vec3(loc_x,loc_y,loc_z);
glm::quat Q;glm::vec3 axis0(0.0f,1.0f,0.0f);
glm::quat R;glm::vec3 axis1(1.0f,0.0f,0.0f);
position = position - target;
//glm::normalize(axis0);
glm::normalize(axis1);
Q = glm::gtx::quaternion::angleAxis( float(angle_x ), axis0 );;
R = glm::gtx::quaternion::angleAxis( float(andl_y ), axis1 );;
glm::quat final = R*Q;
position = final * position;
position = position + target;
cout << "\tPosition: " << position.x << " " << position.y << " " << position.z <<endl;
}
当我测试代码时,使用quat Q的旋转工作正常,但quat R导致“波动”旋转。我做错了什么?
答案 0 :(得分:3)
注意:从my answer here复制。
你所做的就是用四元数有效地实现欧拉角。这没有帮助。
欧拉角的问题在于,当你计算矩阵时,每个角都是相对于它前面的矩阵的旋转。您想要的是获取对象的当前方向,并沿某个轴应用旋转,从而产生新的方向。
你不能用欧拉角做到这一点。您可以使用矩阵,也可以使用四元数(因为它们只是矩阵的旋转部分)。但你不能假装它们是欧拉角。
这是通过不在 all 存储角度来完成的。相反,您只需要一个四元数来表示对象的当前方向。当您决定对其应用旋转(某个轴的某个角度)时,您可以构造一个四元数,表示围绕该轴旋转一个角度。然后右移乘以当前方向四元数的四元数,生成新的当前方向。
渲染对象时,使用当前方向作为方向。
答案 1 :(得分:2)
复制问题:
编辑05/26/2013我如何解决这个问题:
我的代码的问题在于渲染我使用过的场景:
matrix = glm::lookAt(position,looking_at, upDirection);
然后我使用这个矩阵将场景放入相机的视角/基本上渲染相机。然而,当我打电话给我的“Camera :: dolly”(它实际上不应该被称为小车,因为我的目的是旋转相机)功能时,我旋转相机位置而不旋转/更新upDirection(初始化为(0, 1,0)变量。这引起了我所描述的“不稳定”问题,因为按轴(1,0,0)旋转会导致改变upDirection所指向的方向。 代码如下:
glm::quat orient = glm::gtx::quaternion::angleAxis(float(0),0.0f, 0.0f, 1.0f);
void Camera :: rotate(double angle_x,double angle_y,const double&amp; loc_x,const double&amp; loc_y,const double&amp; loc_z,const double&amp; dt){ glm :: vec3 target = glm :: vec3(loc_x,loc_y,loc_z);
position = position - target;
angle_x *= dt;
angle_y *= dt;
glm::quat old_orient = orient;
glm::normalize(orient);
glm::quat q_x_axis = glm::gtx::quaternion::angleAxis(float(angle_y),1.0f, 0.0f, 0.0f) ;
glm::quat q_y_axis = glm::gtx::quaternion::angleAxis(float(angle_x), 0.0f, 1.0f, 0.0f);
orient = orient * q_x_axis * q_y_axis;
upDirection = upDirection * orient;
position = position * (orient);
orient = old_orient;
position = position + target;