简体   繁体   English

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

[英]OpenGL rubiks cube - face rotation with mouse

I am working on my first real OpenGL Project. 我正在开发我的第一个真正的OpenGL项目。 It is a 3x3x3 Rubiks Cube. 这是一个3x3x3 Rubiks立方体。 Here is a link to a simple screenshot of what i have so far( my rubiks cube ) 这是到目前为止我所拥有的简单屏幕截图的链接( 我的rubiks立方体

Rotating the cube is done with dragging the mouse while holding the right mouse button. 通过在按住鼠标右键的同时拖动鼠标来旋转立方体。 This works using the example of a arcball from NeHe Tutorials( NeHe Arcball ) 这是使用NeHe Tutorials( NeHe Arcball )的弧形球的例子

I have the class singleCubes which represents one cube via 6 actual quads, stored in a display list that can be used in it´s draw method. 我有类singleCubes,它通过6个实际四边形表示一个立方体,存储在可以在其绘制方法中使用的显示列表中。 Class ComplexCube has an array of 3x3x3 singleCubes and is used as interface when interacting with the complete rubiks cube. ComplexCube类具有3x3x3单个立方体的数组,并在与完整的rubiks立方体交互时用作接口。

Now i want to rotate each specific face according to the mousedragging with left mouse button down. 现在我想根据mousedragging旋转每个特定的面部,用鼠标左键按下。 I use picking to get the id of the corresponding side of the single cube the user clicked on. 我使用pick来获取用户点击的单个多维数据集的相应边的id。 This works also. 这也有效。 So i click on a side of one cube on a face and depending on the direction of the dragging i set a rotation and offset factor of the cubes that get affected. 所以我点击一个面上一个立方体的一侧,根据拖动的方向,我设置受影响的立方体的旋转和偏移系数。 (i also want to implement that u actually see the face rotate instead of just changing the color) (我也想实现你实际上看到的是旋转面而不是仅仅改变颜色)

Now my Problem is that when i rotate the rubiks cube in any direction with right mouse dragging, it becomes upside down for example. 现在我的问题是,当我用鼠标右键拖动任意方向旋转rubiks立方体时,它会变得颠倒过来。 So when i click on a side and want to rotate the face to the right, it´s going the wrong direction because i can´t keep track if the cube is upside down or whatever. 因此,当我单击一侧并想要将面向右旋转时,它的方向是错误的,因为如果立方体是颠倒的或者其他什么,我无法跟踪。 Due to the use of the arcball rotation i dont have a x- or y-rotation angle which i could use to determine this. 由于使用了弧形旋转,我没有x或y旋转角度,我可以使用它来确定这一点。

Question 1: How can i keep track or later on get the information if the cube is upside down, tilted etc in order to translate the mouse dragging information(when rotating one face) when using the arcball example linked above? 问题1:当使用上面链接的弧形示例时,如果立方体是倒置,倾斜等以便转换鼠标拖动信息(当旋转一个面时),我如何跟踪或稍后获取信息?

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

Setup: C++ with Microsoft Visual Studio 2008, GLEW, freeglut 安装程序:C ++与Microsoft Visual Studio 2008,GLEW,freeglut

You could use gluUnProject to convert mouse coordinates to 3d space and get a vector (difference between two points). 您可以使用gluUnProject将鼠标坐标转换为3d空间并获得一个向量(两点之间的差异)。 This vector could then be used to apply a "force" to the selected face. 然后可以使用该向量将“力”施加到所选择的面部。 Since gluUnProject uses the projection matrix, it would automatically deal with the orientation of the camera. 由于gluUnProject使用投影矩阵,它会自动处理相机的方向。

Basically, once you get your "force" vector, you project it onto the three axes (so onto (1,0,0), (0,1,0), (0,0,1)). 基本上,一旦获得“力”向量,就将其投影到三个轴上(所以在(1,0,0),(0,1,0),(0,0,1)上)。 Then choose the one with the largest magnitude. 然后选择幅度最大的那个。 Then you have to convert this direction into a rotation axis as in the diagram below (sorry for the bad paint skills): 然后你必须将这个方向转换成一个旋转轴,如下图所示(抱歉糟糕的绘画技巧):

解释中使用的向量的示例

So what we have is the "force" vector in black and the selected rubiks face in grey. 所以我们所拥有的是黑色的“力”向量,而选定的红色面向灰色。 To get the rotation axis, just take the cross product the "force" vector with the normal of the selected face. 要获得旋转轴,只需将十字产品的“力”向量与所选面的法线相乘。 This gives the red arrow. 这给出了红色箭头。 From that, you should be able to rotate your cubes in the right direction. 从那以后,您应该能够以正确的方向旋转立方体。

Edit to answer the question in more detail 编辑以更详细地回答问题

So continuing from my explanation, I will give an example of how this will help you. 继续我的解释,我将举例说明这将如何帮助你。 Let's first assume your screen is 800x800 pixels and your rubiks cube is always centred. 我们首先假设您的屏幕是800x800像素,并且您的rubiks立方体始终居中。 Now lets also assume that, as per your drawings in the comments, that we are in the case on the left. 现在让我们假设,根据评论中的图纸,我们在左边的情况下。

We drag the mouse and get two positions which using gluUnProject are transformed into world coordinates (the numbers were chosen to show my point, not by any calculation): 我们拖动鼠标并获得两个位置,使用gluUnProject将其转换为世界坐标(选择数字以显示我的观点,而不是通过任何计算):

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

Now we get the difference vector: p2 - p1 = v = (0.3, -0.05, 0). 现在我们得到差分向量:p2 - p1 = v =(0.3,-0.05,0)。 The reason that I was saying to "project onto the three axes" is so that you extract your major movement (which in this case is 0.3 in the x axis) (since the rubiks cube can't rotate along diagonals). 我之所以说“投射到三个轴上”的原因是你提取你的主要运动(在这种情况下x轴为0.3)(因为rubiks立方体不能沿着对角线旋转)。 To do the "projection" you just have to take the x, y, z axes individually and create vectors from them so you wind up with: 要进行“投影”,你只需要分别取x,y,z轴并从中创建矢量,这样你最终得到:

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

Now take the magnitudes and discard the smallest vectors, so we are left with the vector v1 = (0.3, 0, 0). 现在取大小并丢弃最小的向量,所以我们留下向量v1 =(0.3,0,0)。 This is your movement vector in world space. 这是你在世界空间中的运动矢量。 Now you take the cross product of that vector, with the normal vector of the selected face (which in this case would be (0, 0, 1)). 现在,您使用所选面的法线向量(在这种情况下为(0,0,1))取该向量的叉积。 This gives you a vector which points down (0, 1, 0) (after normalization) (in this step you will probably also have to extract the largest component only (0.02, 1.2, 0.8) -> (0, 1, 0) otherwise you would get bizarre rotations if your camera was not pointing directly along the main axes). 这给你一个向下指向(0,1,0)(归一化后)的向量(在这个步骤中你可能还必须提取最大的成分(0.02,1.2,0.8) - >(0,1,0)否则如果您的相机没有直接指向主轴,您将获得奇怪的旋转。 You can now use that vector as the rotation axis and use 0.3 as your rotation amount (if it rotates in the opposite direciton to that expected, just put a -). 您现在可以使用该向量作为旋转轴,并使用0.3作为旋转量(如果它以与预期相反的方向旋转,只需放置 - )。

Now how does this help if your cube is upside down? 现在,如果您的多维数据集颠倒了,这有什么用呢? Suppose we click on the screen in the same way. 假设我们以相同的方式点击屏幕。 We now get: 我们现在得到:

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

See the difference in the world coordinates? 看世界坐标​​的差异? They are inverted! 他们倒了! So when you take the difference vector p2 - p1 = v = (-0.3, 0.05, 0). 所以当你取差矢量p2 - p1 = v =( - 0.3,3.05,0)时。 Extracting the largest component vector gives (-0.3, 0, 0). 提取最大分量向量给出(-0.3,0,0)。 Doing the cross product once again gives you the rotation axis, but now the rotation is in the opposite direction, which is what you want. 再次执行十字产品会为您提供旋转轴,但现在旋转方向相反,这就是您想要的。

Another reason for the cross product with the normal of the face is that if you were to select the faces on the top (in our drawings), then it would either give a rotation axis along the x or z axes (to the left, or into the screen) which is what you want for the top faces. 与正常面交叉的另一个原因是,如果要选择顶部的面(在我们的图纸中),那么它将沿x或z轴(左侧,或者进入屏幕)这是你想要的顶面。

Like most of us, you will encounter the famous problem called Gimbal Lock. 像我们大多数人一样,你会遇到一个名为Gimbal Lock的着名问题。

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

This problem is extremely well documented so there is not much point for me to go into details here. 这个问题记录得很清楚,因此我没有太多意义在这里详细介绍。 I am sure you will find a ton of information about it. 我相信你会发现很多关于它的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM