
Final week I printed an article about how simple it’s now to implement SceneKit with SwiftUI. Sadly, I found my subsequent mission on this sphere would most actually not be so simple.
The transient is to construct a digital Rubik dice utilizing SceneView operator from SwiftUI. I’ll describe right here how I carried out the animated GIF header picture of this text.
- I would like to attract a dice to symbolize a Rubik dice, a dice that I’ll then assemble into a set of 54 cubes.
- I must implement a digicam view that may enable me to alter the view to unravel the dice.
- I must implement a technique to click on on certainly one of its cubes to alter its orientation.
Simply three necessities that may sound simple however turned out to be fairly a problem.
Bon — the code to construct the dice and shade it was the simplest a part of the mission as you would possibly count on. A job I managed with simply 4 strains of code, nearly.
func addBox(xAxis: Float, yAxis: Float, zAxis: Float)
let cubeNode = SCNNode(geometry: cubeGeometry)
cubeNode.place = SCNVector3(xAxis, yAxis, zAxis)
scene?.rootNode.addChildNode(cubeNode)
After all, I’m oversimplifying it; the feel [colours] took one other ten strains or so. By way of lighting just like the earlier mission, I wished to maintain issues easy and added 4 lights to flood the picture. The nodes [boxes] I added via some nested loops.
I need to confess I had some assistance on SO with implementing this. Within the early construct, I merely used the SceneKit allowsCameraControl
possibility. An possibility that labored properly apart from the truth that it can’t be used alongside the drag gesture. A gesture I wanted to maneuver the person cubes. So I needed to roll my very own.
I did that by making a shared class to log the situation and transaction values of the drag registered in SwiftUI. I then made a digital node [cameraOrbit] that I positioned within the very heart of my Rubik and connected mentioned digicam to it.
Now every time the drag gesture is invoked I retailer the values in my widespread class.
Values I exploit to alter the eular
angles on the cameraOrbit
node. An answer I re-engineered from this SO post — a publish value visiting because it additionally has a wonderful description of what’s going on right here. My model of the code seems like this.
func changeCamera()
let dx = cameraOrbit.eulerAngles.x
let dy = cameraOrbit.eulerAngles.y
let scrollWidthRatio = Float(settings.translation.width / screenWidth) / 16
let scrollHeightRatio = Float(settings.translation.peak / screenHeight) / 16
cameraOrbit.eulerAngles.y = Float(-2 * Float.pi) * scrollWidthRatio + dy
cameraOrbit.eulerAngles.x = Float(-Float.pi) * scrollHeightRatio + dx
This was by far probably the most difficult facet because the hitTest
methodology is a bit damaged, it appears.
I initially tried to implement utilizing the widespread class I had created based mostly on the answer I discovered here. One other wonderful reference I discovered, though sadly, the hittest illustrated inside this resolution wouldn’t work for me.
As a substitute, I carried out the identical type of loop within the delegate methodology of the SceneView, with the code used right here.
In brief, it switches the drag gesture from turning the dice assortment to turning a person dice. A flip makes with a SCNAction
.
It really works moderately properly, though it isn’t fairly proper is it, as I’m certain you’ll agree — getting it proper will take some extra lateral considering on my aspect that I’m going to take offline for now.
This brings me to the top of this paper on SceneKit.
You may obtain a whole copy of the code illustrated from bitbucket here.