Chapter 7: Building a Portal
Last updated
Last updated
func runSession() {
let configuration = ARWorldTrackingConfiguration.init()
configuration.planeDetection = .horizontal
configuration.isLightEstimationEnabled = true
sceneView?.session.run(configuration)
#if DEBUG
sceneView?.debugOptions = [ARSCNDebugOptions.showFeaturePoints]
#endif
} func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
// 所有delegate mathod都是在background thread執行,所以需要丟到Main thread進行UI更新
DispatchQueue.main.async {
if let planeAnchor = anchor as? ARPlaneAnchor {
#if DEBUG
let debugPlaneNode = createPlaneNode(center: planeAnchor.center, extent: planeAnchor.extent)
node.addChildNode(debugPlaneNode)
#endif
self.messageLabel?.text = "Tap on the detected horizontal plane to place the portal"
}
}
} func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
DispatchQueue.main.async {
if let planeAnchor = anchor as? ARPlaneAnchor, node.childNodes.count > 0 {
updatePlaneNode(node.childNodes[0], center: planeAnchor.center, extent: planeAnchor.extent)
}
}
}func createPlaneNode(center: vector_float3, extent: vector_float3) -> SCNNode {
let plane = SCNPlane(width: CGFloat(extent.x), height: CGFloat(extent.z))
let planeMaterial = SCNMaterial()
planeMaterial.diffuse.contents = UIColor.yellow.withAlphaComponent(0.4)
plane.materials = [planeMaterial]
let planeNode = SCNNode(geometry: plane)
planeNode.position = SCNVector3Make(center.x, 0, center.z)
// SceneKit的defult是vertical,因此要轉90度變成平面
planeNode.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0)
return planeNode
}
func updatePlaneNode(_ node: SCNNode, center: vector_float3, extent: vector_float3) {
// 檢查是否為SCNPlane
let gemorty = node.geometry as? SCNPlane
// 根據傳進來anchor的extent訊息來更新gemorty大小
gemorty?.width = CGFloat(extent.x)
gemorty?.height = CGFloat(extent.z)
// 根據傳進來anchor的extent訊息來更新gemorty位置
node.position = SCNVector3Make(center.x, 0, center.z)
}