【ARKit 입문】평면에 아이템을 배치한다

18096 단어 iOSSwiftARKitXcode

평면에 객체 배치



이런 느낌입니다.


이 기사에서는 ARKit을 사용하여 감지된 평면에 항목을 배치하는 구현을 소개합니다.

ARKit에서의 초기 설정이나, 아이템으로서 추가하는 3D 모델의 프로젝트에의 캡처등은 이하를 참조해 주세요~. ;)
· 【ARKit 입문】 우선 할 일
· 【ARKit 입문】Xcode에 3D 파일을 넣어 본다

그럼 본제입니다! !

탭 감지



ARSCNView가 탭되었을 때 그 정보를 받을 필요가 있으므로, 우선 그 검출을 합니다. tapped 메소드에 대해서는 후술합니다.

MainViewController.swift

/// メインのビューのタップを検知するように設定する
    func registerGestureRecognizers() {

        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapped))
        self.mainSceneView.addGestureRecognizer(tapGestureRecognizer)
    }


아이템 버튼



버튼이 탭되면 해당 항목을 선택 상태로 설정합니다.selectedItem의 값은 .scn 파일의 파일 이름입니다.

MainViewController.swift

@IBAction func cupButtonTapped(_ sender: Any) {
        selectedItem = "cup"
    }

    @IBAction func wineButtonTapped(_ sender: Any) {
        selectedItem = "wine_glass"
    }


화면 탭시 처리



화면이 탭되면 sender 탭 위치를 얻고 AR 앵커를 검색합니다. 거기서 AR앵커의 정보가 소득되고 있으면 아이템 추가 처리를 합니다.

MainViewController.swift

@objc func tapped(sender: UITapGestureRecognizer) {
        // タップされた位置を取得する
        let sceneView = sender.view as! ARSCNView
        let tapLocation = sender.location(in: sceneView)

     // タップされた位置のARアンカーを探す
        let hitTest = sceneView.hitTest(tapLocation, types: .existingPlaneUsingExtent)
        if !hitTest.isEmpty {
            // タップした箇所が取得できていればitemを追加
            self.addItem(hitTestResult: hitTest.first!)
        }
    }


아이템 추가 처리



선택한 항목에 해당하는 .scn 파일을 사용하여 노드를 만들고 현실 세계의 좌표를 감지하고 항목을 배치합니다.

MainViewController.swift

    /// アイテム配置メソッド
    func addItem(hitTestResult: ARHitTestResult) {
        if let selectedItem = self.selectedItem {

            // アセットのより、シーンを作成
            let scene = SCNScene(named: "Models.scnassets/\(selectedItem).scn")

            // ノード作成
            let node = (scene?.rootNode.childNode(withName: selectedItem, recursively: false))!

            // 現実世界の座標を取得
            let transform = hitTestResult.worldTransform
            let thirdColumn = transform.columns.3

            // アイテムの配置
            node.position = SCNVector3(thirdColumn.x, thirdColumn.y, thirdColumn.z)
            self.mainSceneView.scene.rootNode.addChildNode(node)
        }
    }


이상으로, 구현 완료입니다! !
마지막으로 전체 샘플 코드를 싣고 있으므로 참고해 주십시오.

또한 앞으로도 ARKit 입문 기사를 투고 예정입니다! ARKit을 사용한 샘플 앱, ARKit에서 사용되는 메서드, 속성에 대해 자세히 살펴보겠습니다. 기대하세요!

전체 샘플 코드



MainViewController.swift

import UIKit
import ARKit

class ViewController: UIViewController{

    @IBOutlet weak var mainSceneView: ARSCNView!

    let configuration = ARWorldTrackingConfiguration()
    var selectedItem: String?

    override func viewDidLoad() {
        super.viewDidLoad()

        initialize()
        registerGestureRecognizers()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    /// ARSCNiew初期化設定    
    func initialize (){

        self.mainSceneView.debugOptions = [ARSCNDebugOptions.showWorldOrigin, ARSCNDebugOptions.showFeaturePoints]
        self.configuration.planeDetection = .horizontal
        self.mainSceneView.session.run(configuration)
        self.mainSceneView.autoenablesDefaultLighting = true
    }

    /// メインのビューのタップを検知するように設定する
    func registerGestureRecognizers() {

        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapped))
        self.mainSceneView.addGestureRecognizer(tapGestureRecognizer)
    }

    @objc func tapped(sender: UITapGestureRecognizer) {
        // タップされた位置を取得する
        let sceneView = sender.view as! ARSCNView
        let tapLocation = sender.location(in: sceneView)

        // タップされた位置のARアンカーを探す
        let hitTest = sceneView.hitTest(tapLocation, types: .existingPlaneUsingExtent)
        if !hitTest.isEmpty {
            // タップした箇所が取得できていればitemを追加
            self.addItem(hitTestResult: hitTest.first!)
        }
    }

    /// アイテム配置メソッド
    func addItem(hitTestResult: ARHitTestResult) {
        if let selectedItem = self.selectedItem {

            // アセットのより、シーンを作成
            let scene = SCNScene(named: "Models.scnassets/\(selectedItem).scn")

            // ノード作成
            let node = (scene?.rootNode.childNode(withName: selectedItem, recursively: false))!

            // 現実世界の座標を取得
            let transform = hitTestResult.worldTransform
            let thirdColumn = transform.columns.3

            // アイテムの配置
            node.position = SCNVector3(thirdColumn.x, thirdColumn.y, thirdColumn.z)
            self.mainSceneView.scene.rootNode.addChildNode(node)
        }
    }


    @IBAction func cupButtonTapped(_ sender: Any) {
        selectedItem = "cup"
    }

    @IBAction func wineButtonTapped(_ sender: Any) {
        selectedItem = "wine_glass"
    }
}

좋은 웹페이지 즐겨찾기