OpenGL rubiks立方体 - 用鼠标旋转面部

时间:2011-10-27 11:26:35

标签: c++ opengl rubiks-cube

我正在开发我的第一个真正的OpenGL项目。这是一个3x3x3 Rubiks立方体。这是到目前为止(my rubiks cube

的简单屏幕截图的链接

旋转立方体是在按住鼠标右键的同时拖动鼠标完成的。这可以使用NeHe Tutorials(NeHe Arcball

中的弧形示例

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

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

现在我的问题是,当我用鼠标右键拖动任意方向旋转rubiks立方体时,它会变得颠倒过来。因此,当我单击一侧并想要将面向右旋转时,它的方向是错误的,因为如果立方体是颠倒的或者其他什么,我无法跟踪。由于使用了弧形旋转,我没有x或y旋转角度,我可以使用它来确定这一点。

问题1:如果多维数据集是倒置,倾斜等,以便在使用时转换鼠标拖动信息(旋转一个面)时,如何跟踪或稍后获取信息以上链接的arcball示例?

// 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

2 个答案:

答案 0 :(得分:4)

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

基本上,一旦获得“力”向量,就将其投影到三个轴上(所以在(1,0,0),(0,1,0),(0,0,1)上)。然后选择幅度最大的那个。然后你必须将这个方向转换为旋转轴,如下图所示(对不起油漆技巧感到抱歉):

Example of the vectors used in the explanation

所以我们所拥有的是黑色的“力”矢量,所选的红宝石面朝灰色。要获得旋转轴,只需将十字产品的“力”向量与所选面的法线相乘。这给出了红色箭头。从那以后,您应该能够以正确的方向旋转立方体。

编辑以更详细地回答问题

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

我们拖动鼠标并获得两个位置,使用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)(因为rubiks立方体不能沿着对角线旋转)。要进行“投影”,你只需要单独选取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,3.05,0)时。提取最大分量向量给出(-0.3,0,0)。再次执行十字产品会为您提供旋转轴,但现在旋转方向相反,这就是您想要的。

与正常面交叉积的另一个原因是,如果你要选择顶部的面(在我们的图纸中),那么它将沿x或z轴给出一个旋转轴(对于离开,或进入屏幕)这是你想要的顶面。

答案 1 :(得分:0)

像我们大多数人一样,你会遇到一个名为Gimbal Lock的着名问题。

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

这个问题记录得很清楚,所以我没有太多意义在这里详细介绍。我相信你会找到关于它的大量信息。