What am I looking for?
A simple explanation of my requirement is this
- Using ARKit, detect an object using iPhone camera
- Find the position of this object on this virtual space
- Place a 3D object on this virtual space using SceneKit. The 3D object should be behind the marker.
An example would be to detect a small image/marker position in a 3D space using camera, place another 3D ball model behind this marker in virtual space (so the ball will be hidden from the user because the marker/image is in front)
What I am able to do so far?
- I am able to detect a marker/image using ARKit
- I am able to position a ball 3D model on the screen.
What is my problem?
I am unable to position the ball in such a way that ball is behind the marker that is detected.
When the ball is in front the marker, the ball correctly hide the marker. You can see in the side view that ball is in front of the marker. See below
But when the ball is behind the marker, opposite doesn't happen. The ball is always seeing in front blocking the marker. I expected the marker to hide the ball. So the scene is not respecting the z depth of the ball's position. See below
Code
Please look into the comments as well
override func viewDidLoad() {
super.viewDidLoad()
sceneView.delegate = self
sceneView.autoenablesDefaultLighting = true
//This loads my 3d model.
let ballScene = SCNScene(named: "art.scnassets/ball.scn")
ballNode = ballScene?.rootNode
//The model I have is too big. Scaling it here.
ballNode?.scale = SCNVector3Make(0.1, 0.1, 0.1)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//I am trying to detect a marker/image. So ImageTracking configuration is enough
let configuration = ARImageTrackingConfiguration()
//Load the image/marker and set it as tracking image
//There is only one image in this set
if let trackingImages = ARReferenceImage.referenceImages(inGroupNamed: "Markers",
bundle: Bundle.main) {
configuration.trackingImages = trackingImages
configuration.maximumNumberOfTrackedImages = 1
}
sceneView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
sceneView.session.pause()
}
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
let node = SCNNode()
if anchor is ARImageAnchor {
//my image is detected
if let ballNode = self.ballNode {
//for some reason changing the y position translate the ball in z direction
//Positive y value moves it towards the screen (infront the marker)
ballNode.position = SCNVector3(0.0, -0.02, 0.0)
//Negative y value moves it away from the screen (behind the marker)
ballNode.position = SCNVector3(0.0, -0.02, 0.0)
node.addChildNode(ballNode)
}
}
return node
}
How to make the scene to respect the z position? Or in other words, how to show a 3D model behind an image/marker that has been detected using ARKit framework?
I am running against iOS 12, using Xcode 10.3. Let me know if any other information is needed.