@ThreeJS简易魔方自动还原实现(一)层先法 - 掘金 写在前面
之前一直对Web3D比较感兴趣,学了Three.js,但一直没有练手机会,学习了不用的话很快就会忘,于是想着之前有玩过魔方,想着将魔方做出网页版本的,最后做成一个在线学习魔方的网站,还希望希望能通过图像识别魔方,自动生成解法。
这次技术选型没有使用原生 Three.js 实现,之前写过一篇快速上手DEMO,大家可以看到使用原生Three.js,即使什么也不做只是在场景中放一个矩形就接近50行代码了,确实有些麻烦。这次选择 react-three-fiber, 这是一个使用React对Three.js进行封装的3D 渲染库,为了将我新学的技术全部都使用上了,这次的技术选型采用 React + Vite +TypeScript+ React-three-fiber的方式实现。
魔方效果可以通过扫描下方的二维码或者访问 https://cube.songxingguo.com/进行查看,源码可以在 Github 中查看。
当然这次,还只是一个初步的模型,还有很多问题,但后面会不断迭代,添加新的功能,比如切换阶数、打乱、还原、以及教程等,并且希望能将我新学的技术都能用到上面。
点击链接查看原文 , 订阅 SSR 获得最新动态。
实现思路
这次是魔方的简单实现,一共分为两步,第一步是实现一个静态魔方,第二步就是让它可以转起来。
实现代码
入门DEMO
在正式开始前,我们先用 react-three-fiber 实现一个最简单的DEMO,同样是实现 快速上手DEMO 中的将一个立方体渲染出来功能,只需要在画布中添加 <Canvas>
,也就相当于three.js中的场景(scene),然后就可以在场景中添加灯光、几何体以及组合这些物体的网格 (Mesh) 。
可以看到,这里只使用了十几行代码,并且只需要按照语法进行配置即可,一目了然,是不是比使用纯原生的Three.js简单了许多。
静态魔方
生成方块
下面我们正式开始实现一个魔方。首先,我们要根据魔方的阶数生成多个小方块,并将它们按一定的位置组装在一起。以最简单的二阶魔方为例,它一共有八个小方块组成,那我们就用循环遍历生成八个小方块,并且计算出它们各自的位置。
这里需要特别注意的一点是,其实对于一个魔方,不管它是二阶、三阶还是N阶、每个面的颜色以及大小怎样,其实生成和旋转的逻辑都是一样的。我门就可以将魔方的属性参数提取成一个常量对象,这样就可以通过配置实现阶数、大小以及魔方颜色的快速变换。
添加材质
上面的代码已经将魔方的骨架搭建好了,接下来我们再根据在每个面的颜色生成对应的纹理 (Texture) ,并将这些纹理分别添加到材质 (Material) 中,这里我们先选用的使用最简单的材质MeshBasicMaterial
, 这种材质不是基于物理的,也就是说不需要灯光也能正常显示,缺点就是会缺少一些真实感,但对于初步实现一个魔方是最简单方便的选择。
魔方转动
事件监听
让魔方转动的整体实现思路是:首先,对鼠标(网页)和触摸(移动端)事件进行监听,在startMouse中获取到用户的点击的起始点,然后再在 moveMouse 中获取到当前移动的点,接着就是计算两个点之间的向量,从而得到用户的旋转方向。最后,根据旋转方向获取到需要旋转的小方块,执行滚动动画。
为了简化事件处理,在魔方的外部包围一个透明的并且和魔方一样大小的立方体,作为事件的代理对象。先给这个透明立方体起一个名称叫做coverCube
,后面就可以直接通过名字获取到它。
获取触摸点
下面详细讲讲具体实现,首先是获取用户触摸点的方法。
这个方法根据当前用户的点击事件获取坐标点,分别对触摸和鼠标操作进行了兼容性处理,获取到二维坐标点。
然后再借助Three.js自带的Raycaster 工具,通过光线投射的方式计算出鼠标在三维场景中经过的点,经过的点可能不止一个,我们只选取第一个叫做coverCube
的元素,返回三维空间中点所在平面的法向量。
计算旋转方向
通过两个点计算出一个三维向量,找到与坐标轴最小的夹角,确定大致方向之后再进一步细化方向。
获取方块
紧接着,根据旋转方向对10取余,得到旋转轴,并将对应平面的小方块加入到需要旋转的数组中。
旋转动画
最后,同样是获取取余获得旋转轴,再根据旋转轴进一步对2取余的得到正(反)旋转方向,进而得到旋转角度。最后,根据旋转轴和旋转角度进行旋转。
扩展阅读