5

我正在研究我的第一个真正的 OpenGL 项目。它是一个 3x3x3 魔方。这是我到目前为止的简单截图的链接(我的魔方

旋转立方体是通过按住鼠标右键拖动鼠标来完成的。这使用来自 NeHe 教程(NeHe Arcball)的轨迹球示例

我有一个类 singleCubes,它通过 6 个实际四边形表示一个立方体,存储在一个显示列表中,可以在它的绘制方法中使用。类 ComplexCube 有一个 3x3x3 singleCubes 数组,在与完整的魔方交互时用作接口。

现在我想根据鼠标左键向下拖动来旋转每个特定的面。我使用pick来获取用户单击的单个立方体的对应侧的ID。这也有效。所以我点击一个立方体的一侧,根据拖动的方向,我设置了受影响的立方体的旋转和偏移因子。(我也想实现你实际上看到脸部旋转而不是仅仅改变颜色)

现在我的问题是,当我用鼠标右键拖动以任何方向旋转魔方时,它会变成上下颠倒。因此,当我单击一侧并想要将面向右旋转时,它会朝错误的方向前进,因为我无法跟踪立方体是否倒置或其他。由于使用了轨迹球旋转,我没有可以用来确定这一点的 x 或 y 旋转角度。

问题 1:当使用上面链接的轨迹球示例时,如果立方体倒置、倾斜等,为了翻译鼠标拖动信息(当旋转一个面时),我如何跟踪或稍后获取信息?

// In render function
glPushMatrix();
{
    glMultMatrixf(Transform.M); // Rotation applied by arcball object
    complCube.draw();           // Draw all the cubes using display lists
}
glPopMatrix();

设置:C++ 和 Microsoft Visual Studio 2008、GLEW、freeglut

4

2 回答 2

4

您可以使用 gluUnProject 将鼠标坐标转换为 3d 空间并获得一个向量(两点之间的差异)。然后可以使用该向量对选定的面施加“力”。由于 gluUnProject 使用投影矩阵,它会自动处理相机的方向。

基本上,一旦你得到你的“力”向量,你就把它投影到三个轴上(所以到(1,0,0),(0,1,0),(0,0,1))。然后选择幅度最大的那个。然后你必须将此方向转换为旋转轴,如下图所示(抱歉绘画技巧不好):

说明中使用的向量示例

所以我们所拥有的是黑色的“力”向量和灰色的选定魔方面。要获得旋转轴,只需将“力”向量与所选面的法线相乘即可。这给出了红色箭头。从此,您应该能够以正确的方向旋转立方体。

编辑以更详细地回答问题

因此,继续我的解释,我将举例说明这将如何帮助您。我们首先假设您的屏幕为 800x800 像素,并且您的魔方始终居中。现在让我们假设,根据您在评论中的图纸,我们在左边的情况下。

我们拖动鼠标,得到两个位置,它们使用 gluUnProject 转换为世界坐标(选择数字来表明我的观点,而不是通过任何计算):

p1 : (600, 600) -> (1, -0.5, 0)
p2 : (630, 605) -> (1.3, -0.505, 0)

现在我们得到差分向量:p2 - p1 = v = (0.3, -0.05, 0)。我说“投影到三个轴上”的原因是为了提取主要运动(在这种情况下,x 轴为 0.3)(因为魔方不能沿对角线旋转)。要进行“投影”,您只需分别获取 x、y、z 轴并从中创建向量,这样您就可以得到:

v1 = (0.3, 0, 0)
v2 = (0, -0.05, 0)
v3 = (0, 0, 0)

现在取大小并丢弃最小的向量,所以我们剩下向量 v1 = (0.3, 0, 0)。这是您在世界空间中的运动矢量。现在,您将该向量与所选面的法线向量(在本例中为 (0, 0, 1))相乘。这为您提供了一个指向 (0, 1, 0) (标准化后)的向量(在此步骤中,您可能还必须仅提取最大分量 (0.02, 1.2, 0.8) -> (0, 1, 0)否则,如果你的相机没有直接指向主轴,你会得到奇怪的旋转)。您现在可以使用该向量作为旋转轴并使用 0.3 作为旋转量(如果它以与预期相反的方向旋转,只需输入 -)。

现在,如果您的立方体倒置,这有什么帮助?假设我们以同样的方式点击屏幕。我们现在得到:

p1 : (600, 600) -> (-1, 0.5, 0)
p2 : (630, 605) -> (-1.3, 0.505, 0)

看到世界坐标的差异了吗?他们颠倒了!所以当你取差分向量 p2 - p1 = v = (-0.3, 0.05, 0) 时。提取最大分量向量得到 (-0.3, 0, 0)。再次做叉积会给你旋转轴,但现在旋转方向相反,这就是你想要的。

与面法线叉积的另一个原因是,如果您要选择顶部的面(在我们的图纸中),那么它会给出沿 x 或 z 轴的旋转轴(向左,或进入屏幕)这是您想要的顶面。

于 2011-10-27T13:25:43.087 回答
0

像我们大多数人一样,您会遇到称为 Gimbal Lock 的著名问题。

见:http ://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=208925

这个问题有很好的记录,所以我在这里没有太多的细节。我相信你会找到很多关于它的信息。

于 2011-10-27T12:36:19.027 回答