我无法在OpenGL上实现轨迹球旋转。当我使用沿X轴向右旋转90度的轨迹球旋转我的立方体(在屏幕上从左向右拖动鼠标)然后尝试旋转它将鼠标从屏幕的顶部拖动到底部,我希望立方体能够沿着我的视角的y轴旋转。相反,它在旋转后沿着ITS轴旋转,从我的角度向侧面旋转。
有人能告诉我我的错误吗?
答案 0 :(得分:5)
听起来你没有使用四元数来表示旋转。如果您使用谷歌“Arcball Graphics Gems”,您应该能够通过Ken Geoemake在Graphic Gems IV中找到代码。
或者,如果您只想要代码,go here。
答案 1 :(得分:3)
+1。您应该始终使用四元数来表示方向和旋转。
另外一个提示:由Gavin Bell实施的Arcball扩展使得旋转球体外的鼠标点击更加直观。它与Glut库的示例here和here一起分发。
它类似于NeHe实现,但是球体内外之间的过渡是平滑的。 Bell的方法用于许多开源3D库,包括:
答案 2 :(得分:0)
我找到了一种非常便宜又脏的方法。
所以OpenGL中的矩阵就像这样
0 1 2 3
4 5 6 7
8 9 10 11
12 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不允许我从状态机中获取当前矩阵。
答案 3 :(得分:0)
这是一个非常古老的问题,但是我遇到了完全相同的问题,当时我正试图将相机代码从learningopengl.com改编成Arcball模型...重要的是,我不想转向四元数,因为使用它们完成的任何操作都可以使用标准的线性代数完成。
我发现的一个解决方案是将弓形球的坐标转换为摄像机坐标(就像弓形球与摄像机一起旋转一样)。
我还使用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( curMouse );
glm::vec3 p2 = screen_to_arcball( prevMouse );
// Rotate arcball to camera coordinates
p1 = glm::vec3( glm::inverse(ViewMatrix) * glm::vec4(p1, 0.0));
p2 = glm::vec3( glm::inverse(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;
}
顺便说一句,我从here获得了screen_to_arcball函数。