import UIKit import SceneKit import ARKit class ViewController: UIViewController, ARSCNViewDelegate { @IBOutlet var sceneView: ARSCNView! var anchorCount = 0 override func viewDidLoad() { super.viewDidLoad() // Set the view's delegate sceneView.delegate = self } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // Create a session configuration let configuration = ARWorldTrackingConfiguration() configuration.sceneReconstruction = .meshWithClassification configuration.environmentTexturing = .automatic sceneView.automaticallyUpdatesLighting = true sceneView.autoenablesDefaultLighting = true // Run the view's session sceneView.session.run(configuration) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // Pause the view's session sceneView.session.pause() } func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { guard let meshAnchor = anchor as? ARMeshAnchor else { return } let meshGeometry = ARSCNMeshGeometry(meshAnchor: meshAnchor) meshGeometry.node.name = anchor.name node.addChildNode(meshGeometry.node(material: UIColor.blue)) anchorCount += 1 } // scene update independent of drawing // data stays coherent for duration of render // Xcode instruments for resource monitoring /* Game performance template */ func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) { guard let meshAnchor = anchor as? ARMeshAnchor else { return } if let previousMeshNode = sceneView.scene.rootNode.childNode(withName: meshAnchor.name ?? "", recursively: true) { previousMeshNode.removeFromParentNode() } let meshGeometry = ARSCNMeshGeometry(meshAnchor: meshAnchor) node.addChildNode(meshGeometry.node(material: UIColor.blue)) } } class ARSCNMeshGeometry { let scnGeometry: SCNGeometry var node: SCNNode { return SCNNode(geometry: scnGeometry) } init(meshAnchor: ARMeshAnchor) { let meshGeometry = meshAnchor.geometry // Vertices source let vertices = meshGeometry.vertices let verticesSource = SCNGeometrySource(buffer: vertices.buffer, vertexFormat: vertices.format, semantic: .vertex, vertexCount: vertices.count, dataOffset: vertices.offset, dataStride: vertices.stride) // Indices Element let faces = meshGeometry.faces let facesData = Data(bytesNoCopy: faces.buffer.contents(), count: faces.buffer.length, deallocator: .none) let facesElement = SCNGeometryElement(data: facesData, primitiveType: .triangles, primitiveCount: faces.count, bytesPerIndex: faces.bytesPerIndex) // Enabling this print statement causes the app to continue // print(faces.count) scnGeometry = SCNGeometry(sources: [verticesSource], elements: [facesElement]) } func node(material: Any) -> SCNNode { let scnMaterial = SCNMaterial() scnMaterial.diffuse.contents = material let geometry = scnGeometry geometry.materials = [scnMaterial] return SCNNode(geometry: geometry) } }