Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Create a horizontal plane detector and replace the surface with an image
import UIKit
import ARKit
import SceneKit
class ViewController: UIViewController, ARSCNViewDelegate {
@IBOutlet weak var sceneView: ARSCNView!
let configuration = ARWorldTrackingConfiguration()
override func viewDidLoad() {
super.viewDidLoad()
// set delegate so renderer fn gets called
sceneView.delegate = self
// set debug options using an array
sceneView.debugOptions = [ARSCNDebugOptions.showWorldOrigin, ARSCNDebugOptions.showFeaturePoints]
// type of plane detection
configuration.planeDetection = .vertical
// run, requests camera access first run
sceneView.session.run(configuration)
}
// create surface, in this case grass aka "turf", but could be anything depending on image
func createTurf(planeAnchor: ARPlaneAnchor) -> SCNNode {
// create scene node
let turfNode = SCNNode(geometry: SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z)))
// now set node properties such as material and position
turfNode.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "ocean")
turfNode.geometry?.firstMaterial?.isDoubleSided = true
turfNode.position = SCNVector3(planeAnchor.center.x, planeAnchor.center.y, planeAnchor.center.z)
// use extension to rotate 90 degrees about x axis <--x-->
turfNode.eulerAngles = SCNVector3(-90.degreesToRadians, 0, 0)
return turfNode
}
// This delegate fires when an anchor is added whenever an ARAnchor was added to the sceneview. An anchor encodes position, size and orientation of something ... the surface in this case.
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
print("New surface detected")
// notice that we {return} early if we don't have an anchor
guard let planeAnchor = anchor as? ARPlaneAnchor else {return}
// ... otherwise we proceed creating and adding the scene node
let turfNode = createTurf(planeAnchor: planeAnchor)
node.addChildNode(turfNode)
}
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
print("Surface updated")
guard let planeAnchor = anchor as? ARPlaneAnchor else {return}
node.enumerateChildNodes { (childNode, _) in
childNode.removeFromParentNode()
}
let turfNode = createTurf(planeAnchor: planeAnchor)
node.addChildNode(turfNode)
}
func renderer(_ renderer: SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor) {
print("Surface anchor removed")
node.enumerateChildNodes { (childNode, _) in
childNode.removeFromParentNode()
}
}
}
extension Int {
var degreesToRadians: Double { return Double(self) * .pi/180 }
}
@jungchris

This comment has been minimized.

Copy link
Owner Author

@jungchris jungchris commented Sep 17, 2020

Made a few edits to update the code and provide better comments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.