Press ESC to close

ARKit ile Zemin Algılama

Merhaba arkadaşlar, bu yazımızda ARKit ile nasıl zemini algılarız ve zemini algıladığımızda nasıl model ekleriz bundan bahsedeceğiz. Bildiğiniz gibi ARKit bir çok farklı şekilde ve bir çok farklı amaçta kullanılıyor. Bu amaçlardan biri de kullanıcının bulunduğu, yürüdüğü zemini tespit etmek. Bunun için Swift ARKit ile kolayca tespit edebilir ve burada bir alan ekleyebiliriz. Daha önceki ARKit ile oluşturduğumuz yazılara buradan ulaşabilirsiniz.

Yapacağımız örnek projede zemin algıladığımız zaman lavlardan oluşan bir resim koyacağız. Daha önceki yaptığımız tasarımlarda olduğu gibi ekranımıza bir SceneKit koyalım ve ardından kod yazmaya baslayabiliriz.

Oluşturmuş olduğumuz SceneView’e bir configuration vermemiz lazım. Configuration verirken plane detection kısmına ise horizontal kısmını set etmeliyiz. Bu sayede Apple’ın API’si yatayda bir alan bulduğu zaman didAdd methoduna düşecektir. Bu methoda geldiği zaman ise lavlardan oluşan bir image’i node olarak ekliyoruz.

Aşağıdaki örnekte nasıl sileceğimizi ve nasıl güncelleyeceğimizi gösteren fonksiyonlar da mevcut. Projenin son haline buradan ulaşabilirsiniz.

import UIKit
import ARKit

class ViewController: UIViewController {

    @IBOutlet weak var sceneView: ARSCNView!
    let configuration = ARWorldTrackingConfiguration()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setUI()
    }

    func setUI() {
        // MARK: sceneView
        sceneView.delegate = self
        sceneView.debugOptions = [.showWorldOrigin, .showFeaturePoints]
        configuration.planeDetection = .horizontal
        sceneView.session.run(configuration)
    }
    
    func createLava() -> SCNNode {
        let lavaNode = SCNNode(geometry: SCNPlane(width: 1, height: 1))
        lavaNode.geometry?.firstMaterial?.diffuse.contents =  UIImage(named: "lava")
        lavaNode.geometry?.firstMaterial?.isDoubleSided = true
        lavaNode.position = SCNVector3(0, 0, -1)
        lavaNode.eulerAngles = SCNVector3(90.degreesToRadians, 0, 0)
        return lavaNode
    }
    
    func createLava(planeAnchor: ARPlaneAnchor) -> SCNNode {
        let lavaNode = SCNNode(geometry: SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z)))
        lavaNode.geometry?.firstMaterial?.diffuse.contents =  UIImage(named: "lava")
        lavaNode.geometry?.firstMaterial?.isDoubleSided = true
        lavaNode.position = SCNVector3(planeAnchor.center.x, planeAnchor.center.y, planeAnchor.center.z)
        lavaNode.eulerAngles = SCNVector3(90.degreesToRadians, 0, 0)
        return lavaNode
    }
}

extension ViewController: ARSCNViewDelegate {
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
        print("new flat surface detected, new arplaneanchor added")
        let lavaNode = createLava(planeAnchor: planeAnchor)
        node.addChildNode(lavaNode)
    }
    
    func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
        guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
        print("updating floor's anchor")
        node.enumerateChildNodes { childNode, _ in
            childNode.removeFromParentNode()
        }
        let lavaNode = createLava(planeAnchor: planeAnchor)
        node.addChildNode(lavaNode)
    }
    
    func renderer(_ renderer: SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor) {
        guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
        node.enumerateChildNodes { childNode, _ in
            childNode.removeFromParentNode()
        }
    }
}

extension Int {
    var degreesToRadians: Double { return Double(self) * .pi / 180}
}

Sorularınız olursa mail veya yorum atarak ulaşabilirsiniz. İyi çalışmalar.

 

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir