作成したアプリ
水平面のNodeを拡大するアプリです。実装方法を説明します。

事前準備
info.plistにカメラの許可
「Privacy – Camera Usage Description」を追加します。

ARSCNViewを画面全体に配置しoutletで取得

制約は左右上下全て0としてください。
使えるようにViewControllerにoutletで取得する
@IBOutlet weak var sceneView: ARSCNView
水平面を検出する設定を行う
sceneViewのセッションを開始するためにARWorldTrackingConfiguration()を作成
ARWorldTrackingConfigurationのplaneDetectionを.horizontal(水平)に設定
sceneViewのsessionをrunし、sceneViewのdelegateをセットする。
let configuration = ARWorldTrackingConfiguration()
override func viewDidLoad() {
super.viewDidLoad()
sceneView.debugOptions = [.showWorldOrigin,.showFeaturePoints]
configuration.planeDetection = .horizontal
sceneView.session.run(configuration)
sceneView.delegate = self
}
平面のNodeを作る関数の作成createPlane
ARPlaneAnchorを引数としてSCNNodeを返す関数を作成する
作成するNodeの位置とサイズは引数のplaneAnchorから取得する
ここで重要なのがNodeの角度(eulerAngles)をx軸に90°回転させること
func createPlane(planeAnchor:ARPlaneAnchor)->SCNNode{
//Nodeの大きさはplaneAnchorの大きさに合わせる
let planeNode = SCNNode(geometry: SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z)))
planeNode.geometry?.firstMaterial?.diffuse.contents = UIColor.green
planeNode.geometry?.firstMaterial?.isDoubleSided = true
//Nodeの位置はplaneAnchorの中央に合わせる
planeNode.position = SCNVector3(x: planeAnchor.center.x, y: planeAnchor.center.y, z: planeAnchor.center.z)
//90度回転させて水平のNodeにする
planeNode.eulerAngles = SCNVector3(x: Float(90.degreeToRadians), y: 0, z: 0)
return planeNode
}
extension Int{
var degreeToRadians:Double{return Double(self) * .pi/180}
}
ARSCNViewDelegateで呼ばれるメソッドで平面Node作成関数を呼ぶ
- 水平面を検出する毎に呼ばれるdidAddでcreatePlaneで平面Nodeを追加
- 水平面が拡大する毎に呼ばれるdidUpdateで既存の平面Node削除し新たに平面Nodeを追加
- 水平面を削除する毎に呼ばれるdidRemoveで平面Node削除
extension ViewController:ARSCNViewDelegate{
//面を検出する毎に呼ばれる
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else {return}
let planeNode = createPlane(planeAnchor: planeAnchor)
node.addChildNode(planeNode)
print("detect")
}
//面が拡大すると呼ばれる
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else {return}
node.enumerateChildNodes { childNode, _ in
childNode.removeFromParentNode()
}
let planeNode = createPlane(planeAnchor: planeAnchor)
node.addChildNode(planeNode)
print("update")
}
//面を削除すると呼ばれる
func renderer(_ renderer: SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else {return}
node.enumerateChildNodes { childNode, _ in
childNode.removeFromParentNode()
}
}
}
まとめ
検出した水平面は拡大していくので、拡大する毎にNodeを削除、追加で平面の拡大で広がるNodeを作成することが可能です。
iOS開発のおすすめ書籍
あの実装方法どうだったっけ?を解決してくれます。swiftの文法から部品、ネットワーク、各種センサーなど端末機能の使い方まで対応しており、あると便利な一冊です。
Swiftの勉強をするならUdemyがおすすめ!
私はUdemyでSwiftの勉強をしてアプリを自作して公開出来るようになりました。
特に以下のコースは基礎的なUIKitの使い方からAR、機械学習(CoreML)までiOSの機能を網羅しており、図解が豊富なハンズオン形式なのでアプリを作りながら楽しく学べます。
2022/12/27時点で評価数80000越えのSwiftのトップコースです。
iOS & Swift – The Complete iOS App Development Bootcamphttps://www.udemy.com/courses/search/?src=ukw&q=swift
初回は大幅な割引があったり、Udemyは定期的な割引もしていますので良ければ是非。
なお上記は英語のコースになりますが日本語字幕に対応しています。一応以下で英語コースの勉強方法(日本語化)を記載しています。ご参考にどうぞ。
もしご参考になりましたら下部にある役に立ったボタン、TwitterなどSNSへの投稿をしていただけると励みになります
コメント