I would like to draw a Focus Circle
and a shadow inside it on a plane beneath the object I'm placing to, like in IKEA AR application.
How do I do that?
To create a Focus Circle
, like in Ikea AR app, I recommend you use a png
file with a premultiplied RGBA channels like this one (drag-and-drop it on your Desktop for testing)
import SceneKit
let scene = SCNScene(named: "chair.scn")!
let sceneView = self.view as! SCNView
sceneView.scene = scene
sceneView.allowsCameraControl = true
sceneView.backgroundColor = .black
let focusCircle = SCNNode()
focusCircle.geometry = SCNPlane(width: 1.0, height: 1.0)
focusCircle.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "crcl")
focusCircle.position.y = 0.01
focusCircle.eulerAngles.x = -.pi/2
scene.rootNode.addChildNode(focusCircle)
let actionA = SCNAction.scale(to: 0.1, duration: 0.5)
let actionB = SCNAction.scale(to: 0.9, duration: 0.5)
let sequence = SCNAction.sequence([actionA, actionB])
focusCircle.runAction(SCNAction.repeatForever(sequence))
For generating a shadow you need to add a directional
light in your scene. Here's the code:
let sun = SCNNode()
sun.light = SCNLight()
sun.light!.type = .directional
sun.light!.castsShadow = true
sun.light!.shadowMode = .deferred
sun.light!.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5)
sun.rotation = SCNVector4(x: -1, y: 0, z: 0, w: .pi/2)
scene.rootNode.addChildNode(sun)
Then you need to create an invisible plane for your semi-transparent shadow:
let shadowPlane = SCNNode()
shadowPlane.geometry = SCNFloor()
shadowPlane.geometry?.firstMaterial!.colorBufferWriteMask = []
shadowPlane.geometry?.firstMaterial!.readsFromDepthBuffer = true
shadowPlane.geometry?.firstMaterial!.writesToDepthBuffer = true
shadowPlane.geometry?.firstMaterial!.lightingModel = .shadowOnly
scene.rootNode.addChildNode(shadowPlane)
Using the RealityKit SDK to create a Focus Circle
is even easier because the framework has a VideoMaterial. Read this post to find out how to implement RealityKit's video material to a plane.