Created
December 18, 2020 08:51
-
-
Save VAnsimov/08e0918445cb9f750abd6b39a4003e50 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import ARKit | |
extension ARPlaneAnchor { | |
@discardableResult | |
func addPlaneNode(on node: SCNNode, geometry: SCNGeometry, contents: Any) -> SCNNode { | |
guard let material = geometry.materials.first else { fatalError() } | |
if let program = contents as? SCNProgram { | |
material.program = program | |
} else { | |
material.diffuse.contents = contents | |
} | |
let planeNode = SCNNode(geometry: geometry) | |
DispatchQueue.main.async(execute: { | |
node.addChildNode(planeNode) | |
}) | |
return planeNode | |
} | |
func addPlaneNode(on node: SCNNode, contents: Any) { | |
let geometry = SCNPlane(width: CGFloat(extent.x), height: CGFloat(extent.z)) | |
let planeNode = addPlaneNode(on: node, geometry: geometry, contents: contents) | |
planeNode.transform = SCNMatrix4MakeRotation(-Float.pi / 2.0, 1, 0, 0) | |
} | |
func findPlaneNode(on node: SCNNode) -> SCNNode? { | |
for childNode in node.childNodes { | |
if childNode.geometry as? SCNPlane != nil { | |
return childNode | |
} | |
} | |
return nil | |
} | |
func findShapedPlaneNode(on node: SCNNode) -> SCNNode? { | |
for childNode in node.childNodes { | |
if childNode.geometry as? ARSCNPlaneGeometry != nil { | |
return childNode | |
} | |
} | |
return nil | |
} | |
@available(iOS 11.3, *) | |
func findPlaneGeometryNode(on node: SCNNode) -> SCNNode? { | |
for childNode in node.childNodes { | |
if childNode.geometry as? ARSCNPlaneGeometry != nil { | |
return childNode | |
} | |
} | |
return nil | |
} | |
@available(iOS 11.3, *) | |
func updatePlaneGeometryNode(on node: SCNNode) { | |
DispatchQueue.main.async(execute: { | |
guard let planeGeometry = self.findPlaneGeometryNode(on: node)?.geometry as? ARSCNPlaneGeometry else { return } | |
planeGeometry.update(from: self.geometry) | |
}) | |
} | |
func updatePlaneNode(on node: SCNNode) { | |
DispatchQueue.main.async(execute: { | |
guard let plane = self.findPlaneNode(on: node)?.geometry as? SCNPlane else { return } | |
guard !PlaneSizeEqualToExtent(plane: plane, extent: self.extent) else { return } | |
plane.width = CGFloat(self.extent.x) | |
plane.height = CGFloat(self.extent.z) | |
}) | |
} | |
} | |
fileprivate func PlaneSizeEqualToExtent(plane: SCNPlane, extent: vector_float3) -> Bool { | |
if plane.width != CGFloat(extent.x) || plane.height != CGFloat(extent.z) { | |
return false | |
} else { | |
return true | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class PlaneDetectionViewController: UIViewController, ARSCNViewDelegate { | |
@IBOutlet var sceneView: ARSCNView! | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
sceneView.delegate = self | |
sceneView.scene = SCNScene() | |
sceneView.debugOptions = [SCNDebugOptions.showFeaturePoints] | |
} | |
override func viewWillAppear(_ animated: Bool) { | |
super.viewWillAppear(animated) | |
let configuration = ARWorldTrackingConfiguration() | |
configuration.planeDetection = .horizontal | |
sceneView.session.run(configuration) | |
} | |
override func viewWillDisappear(_ animated: Bool) { | |
super.viewWillDisappear(animated) | |
sceneView.session.pause() | |
} | |
// MARK: - ARSCNViewDelegate | |
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { | |
guard let planeAnchor = anchor as? ARPlaneAnchor else { fatalError() } | |
planeAnchor.addPlaneNode(on: node, contents: UIColor.arBlue.withAlphaComponent(0.3)) | |
} | |
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) { | |
guard let planeAnchor = anchor as? ARPlaneAnchor else { fatalError() } | |
planeAnchor.updatePlaneNode(on: node) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ARKit | |
class ShapedPlaneViewController: UIViewController, ARSCNViewDelegate { | |
@IBOutlet var sceneView: ARSCNView! | |
private let device = MTLCreateSystemDefaultDevice()! | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
sceneView.delegate = self | |
sceneView.scene = SCNScene() | |
sceneView.debugOptions = [SCNDebugOptions.showFeaturePoints, SCNDebugOptions.showWireframe] | |
} | |
override func viewWillAppear(_ animated: Bool) { | |
super.viewWillAppear(animated) | |
let configuration = ARWorldTrackingConfiguration() | |
configuration.planeDetection = [.vertical, .horizontal] | |
sceneView.session.run(configuration) | |
} | |
override func viewWillDisappear(_ animated: Bool) { | |
super.viewWillDisappear(animated) | |
sceneView.session.pause() | |
} | |
// MARK: - ARSCNViewDelegate | |
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { | |
print("\(self.classForCoder)/" + #function + ", anchor id: \(anchor.identifier)") | |
guard let planeAnchor = anchor as? ARPlaneAnchor else {fatalError()} | |
let planeGeometry = ARSCNPlaneGeometry(device: device)! | |
planeGeometry.update(from: planeAnchor.geometry) | |
let color = planeAnchor.alignment == .horizontal ? UIColor.arBlue : UIColor.green | |
planeAnchor.addPlaneNode(on: node, geometry: planeGeometry, contents: color.withAlphaComponent(0.3)) | |
} | |
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) { | |
guard let planeAnchor = anchor as? ARPlaneAnchor else {fatalError()} | |
if let planeGeometry = planeAnchor.findShapedPlaneNode(on: node)?.geometry as? ARSCNPlaneGeometry { | |
planeGeometry.update(from: planeAnchor.geometry) | |
} | |
} | |
func renderer(_ renderer: SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor) { | |
print("\(self.classForCoder)/" + #function) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment