Member-only story
Build a Rubik Cube Using SceneView and SwiftUI
Solve the cube within your apps

Last week I published an article about how easy it is now to implement SceneKit with SwiftUI. Sadly, I discovered my next project in this sphere would most certainly not be so straightforward.
The brief is to build a virtual Rubik cube using SceneView operator from SwiftUI. I will describe here how I implemented the animated GIF header image of this article.
Challenges
- I need to draw a cube to represent a Rubik cube, a cube that I will then assemble into a collection of 54 cubes.
- I need to implement a camera view that will allow me to change the view to solve the cube.
- I need to implement a way to click on one of its cubes to change its orientation.
Just three requirements that might sound easy but turned out to be quite a challenge.
The Cube
Bon — the code to build the cube and color it was the easiest part of the project as you might expect. A job I managed with just 4 lines of code, almost.
func addBox(xAxis: Float, yAxis: Float, zAxis: Float) {
let cubeNode = SCNNode(geometry: cubeGeometry)
cubeNode.position = SCNVector3(xAxis, yAxis, zAxis)
scene?.rootNode.addChildNode(cubeNode)
}
Of course, I am oversimplifying it; the texture [colours] took another ten lines or so. In terms of lighting like the previous project, I wanted to keep things simple and added four lights to flood the image. The nodes [boxes] I added through some nested loops.
The Camera
I must confess I had some help on SO with implementing this. In the early build, I simply used the SceneKit allowsCameraControl
option. An option that worked well except for the fact that it cannot be used alongside the drag gesture. A gesture I needed to move the individual cubes. So I had to roll my own.
I did that by creating a shared class to log the location and transaction values of the drag registered in SwiftUI. I then made a virtual node [cameraOrbit] that I placed in the very center of my Rubik and attached said camera to it.