如何使用GLM完成魔方旋转的编号重排
2016-06-03 本文已影响389人
Kent_Zhang
本文相当干货,包含数学应用技巧。
前些日子,老大让各种小弟学习OpenGL渲染等等,一个主要的大作业就是用OpenGL绘制会旋转的魔方。
大体的思路就是画三角形面=》两个三角形面形成一个正方形面=》6个正方形面旋转位移形成小立方体=》多个小立方体位移得到魔方
静态的魔方绘制起来没啥难度,但是要做随机方向和层的魔方旋转,问题就出来了。
假设只是2x2x2的2阶魔方,设上层左上角的方块编号为1,上层顺时针旋转之后,编号1的方块就到了编号为2的位置。每次旋转都需要重新设置方块的编号,以便下次旋转修改其模型矩阵。
只是2阶或者3阶魔方的时候,这种编号的重设可以穷举解决。但是多阶魔方的时候,这种编号重设就难以找到规律进行简化。
由此,我找了一种技巧,无论几阶魔方,都可以简单轻松的重设编号,每次旋转操作都可以找到对应的魔方方块。
招数就是方块编号使用3维向量。以下使用glm与C++代码做为示例。并且用左手坐标系(z轴向上)。
例如2阶魔方中,如果一个小方块位于上层的右下角,那么给予其一个向量编号pos(1,1,1),即(x轴正向为右,y轴正向朝外,z轴正向朝上)。那么以z轴为轴旋转90度,可以理解为对pos做旋转操作,以数学进行表达就是用旋转矩阵叉乘pos向量。glm+C++代码如下:
glm::vec3 pos(1,1,1);
glm::mat4 rotate_mat = glm::rotate(glm::mat4(1.0), glm::radians(90.0), glm::vec3(0,0,1));
pos = glm::vec3(rotate_mat * glm::vec4(pos, 1.0));
代码运行之后,得到pos为(1,-1,1)之类的旋转后的方块编号。不过由于有计算误差的情况,有时候会得到(0.99999, -0.999999, 1)之类的,此时对每个xyz值做一个浮点值近似判断就可以了。
每一个方块存储一个pos向量作为位置编号,每次对方块完成旋转要重设编号的时候对pos做上述向量旋转操作,这样再次旋转的时候就可以轻松的找到需要旋转的对应方块了。