OpenGL中的轨迹球旋转
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL中的轨迹球旋转相关的知识,希望对你有一定的参考价值。
我无法在OpenGL上实现轨迹球旋转。当我使用轨迹球沿X轴向右旋转90度来旋转立方体(在屏幕上从左向右拖动鼠标),然后尝试旋转它时,将鼠标从屏幕的顶部拖动到屏幕的底部,我希望立方体沿我的透视图的y轴旋转。相反,它在旋转后沿ITS y轴旋转,从我的角度来看向侧面旋转。
有人可以告诉我我可能做错了什么吗?
听起来您没有使用四元数来表示旋转。如果您使用Google搜索“ Arcball Graphics Gems”,那么应该可以在Kenshoemake的Graphic Gems IV中找到代码。
或者,如果您只想要代码,则为go here。
+ 1为Daniel关于四元数和Arcball的建议。您应该始终使用四元数来表示方向和旋转。
另一个提示:Gavin Bell实现了Arcball的扩展,使鼠标在旋转球体之外的点击更加直观。它在Glut库的示例here和here中分发。
与NeHe实现类似,但是球体内部和外部之间的过渡是平滑的。 Bell的方法已在许多开源3D库中使用,包括:
- Blender project
- Meshlab / VCGlib。
我找到了一种非常便宜又肮脏的方法。所以OpenGL中的矩阵是这样的0 1 2 34 5 6 78 9 10 1112 13 14 15
如果您将3个垂直数字用作旋转矢量,则将获得所需的效果。例如:
如果绕矢量(0,4,8)旋转,则将绕x轴旋转。同样(1,5,9)将为y,(3,6,10)将为z。为什么行得通?....好吧,当您取垂直数字时,您制作了原始矩阵的转置副本,与旋转的矩阵相比,它为您提供了某种原始矩阵....对不起,我不知道数学家,但有效。相信我 ;)。我在OpenGL ES上的示例代码:
Matrix.rotateM(Settings.anchorMatrix, 0, rX, Settings.anchorMatrix[0], Settings.anchorMatrix[4], Settings.anchorMatrix[8]);
Matrix.rotateM(Settings.anchorMatrix, 0, rY, Settings.anchorMatrix[1], Settings.anchorMatrix[5], Settings.anchorMatrix[9]);
Matrix.rotateM(Settings.anchorMatrix, 0, rZ, Settings.anchorMatrix[2], Settings.anchorMatrix[6], Settings.anchorMatrix[10]);
anchorMatrix从技术上讲是我在侧面创建的用于跟踪的主要矩阵。 android OpenGL ES不允许我从状态机中获取当前矩阵。
这是一个非常老的问题,但是我碰到了[[完全相同的问题,我不想转向四元数,因为使用它们完成的任何操作都可以使用标准的线性代数完成。
我发现的解决方案是将弓形球的坐标转换为摄影机坐标(我认为-好像弓形球与摄影机一起旋转)。我还使用Rodrigues公式旋转了相机的位置,前向和上向矢量,然后诉诸glm:LookAt返回最终的ViewMatrix(将顶点着色器相乘的那个)。
我的代码如下:
// Processes input received from a mouse input system.
void ProcessMouseMovement(glm::vec2 prevMouse, glm::vec2 curMouse)
glm::vec3 p1 = screen_to_arcball( prevMouse );
glm::vec3 p2 = screen_to_arcball( curMouse );
// Rotate arcball to camera coordinates
p1 = glm::vec3( ViewMatrix * glm::vec4(p1, 0.0));
p2 = glm::vec3( ViewMatrix * glm::vec4(p2, 0.0));
glm::vec3 axis = glm::cross(p1, p2);
float angle = std::acos(glm::dot(p1,p2));
if ( angle > 0.001f)
// Rotate
Position = rotate_axis_angle(Position, axis, angle);
Front = rotate_axis_angle(Front, axis, angle);
Up = rotate_axis_angle(Up, axis, angle);
ViewMatrix = glm::lookAt(Position, Position + Front, Up);
// Get Arcball coordinates from screen
glm::vec3 screen_to_arcball(const glm::vec2 &p)
const float dist = glm::dot(p, p);
if (dist < 0.999f)
// If we're on/in the sphere return the point on it
return glm::vec3(p.x, p.y, std::sqrt(1.f - dist));
else
// otherwise we project the point onto the sphere
const glm::vec2 proj = glm::normalize(p);
return glm::vec3(proj.x, proj.y, 0.f);
// Rotate vector given (angle,axis) using Rodrigues' formula
glm::vec3 rotate_axis_angle(glm:: vec3 &vec, glm:: vec3 axis, float angle)
axis = glm::normalize(axis);
glm::vec3 cross_axis = glm::cross(axis, vec);
vec = vec * std::cos(angle) + axis * glm::dot(axis,vec) * (1.0f - std::cos(angle)) + cross_axis * std::sin(angle);
return vec;
以上是关于OpenGL中的轨迹球旋转的主要内容,如果未能解决你的问题,请参考以下文章