简体   繁体   English

是否可以使用ARKit检测放置有物体的地板?

[英]Is it possible to detect floor with objects placed on it using ARKit?

我想使用ARkit检测地板,当存在物体(如桌子等)并希望对检测到的表面进行着色时,是否可以使用ARkit进行检测?我是ARKit世界中的新手,不确定是否可行以及从何处开始。

Your session configuration function should be like this, you call it on viewWillAppear 您的会话配置函数应如下所示,您可以在viewWillAppear上调用它

func setUpSceneView() {
        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = .horizontal

        sceneView.session.run(configuration)

        sceneView.delegate = self
        sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints]
    }

you can also use .vertical for walls or whatever.. 您还可以将.vertical用作墙壁或其他材质。

on view did load add a tapGestureRecognizer to the scene so that you can add the SCNNode where you tap to the detected surface 在视图上确实加载了一个tapGestureRecognizer到场景中,这样您就可以将您点击的SCNNode添加到检测到的表面

addTapGestureToSceneView() inside viewDidLoad viewDidLoad中的addTapGestureToSceneView()

func addTapGestureToSceneView() {
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(placeOnSurface.addNodeToSceneView(withGestureRecognizer:)))
        sceneView.addGestureRecognizer(tapGestureRecognizer)
    }

the method addNodeToSceneView will place SNNode on surface when it detects the plane.. 方法addNodeToSceneView在检测到平面时会将SNNode放置在表面上。

@objc func addShipToSceneView(withGestureRecognizer recognizer: UIGestureRecognizer) {
        let tapLocation = recognizer.location(in: sceneView)
        let hitTestResults = sceneView.hitTest(tapLocation, types: .existingPlaneUsingExtent)

        guard let hitTestResult = hitTestResults.first else { return }
        let translation = hitTestResult.worldTransform.translation
        let x = translation.x
        let y = translation.y
        let z = translation.z

        var name:String = "YourModel.obj" //you can add node whatever


        let group = DispatchGroup()
        group.enter()
        DispatchQueue.global(qos: .background).async {
            print("This is run on the background queue")

            let tempScene = SCNScene(named: name)!
            var geom:SCNGeometry = tempScene.rootNode.childNodes[0].geometry!
            var boxNode:SCNNode = SCNNode(geometry: geom)
            boxNode.position = SCNVector3(x,y,z)
            self.sceneView.scene.rootNode.addChildNode(boxNode)
            group.leave()

        }
        group.notify(queue: .main){
            //Here you know that the node is has been put
        }
    }

and you need some functions for render



    extension float4x4 {
    var translation: float3 {
        let translation = self.columns.3
        return float3(translation.x, translation.y, translation.z)
    }
}



    extension placeOnSurface: ARSCNViewDelegate {
        func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
            // 1
            guard let planeAnchor = anchor as? ARPlaneAnchor else { return }

            // 2
            let width = CGFloat(planeAnchor.extent.x)
            let height = CGFloat(planeAnchor.extent.z)
            let plane = SCNPlane(width: width, height: height)

            // 3
            plane.materials.first?.diffuse.contents = UIColor.transparentLightBlue

            // 4
            let planeNode = SCNNode(geometry: plane)

            // 5
            let x = CGFloat(planeAnchor.center.x)
            let y = CGFloat(planeAnchor.center.y)
            let z = CGFloat(planeAnchor.center.z)
            planeNode.position = SCNVector3(x,y,z)
            planeNode.eulerAngles.x = -.pi / 2

            // 6
            node.addChildNode(planeNode)
        }

        func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
            // 1
            guard let planeAnchor = anchor as?  ARPlaneAnchor,
                let planeNode = node.childNodes.first,
                let plane = planeNode.geometry as? SCNPlane
                else { return }

            // 2
            let width = CGFloat(planeAnchor.extent.x)
            let height = CGFloat(planeAnchor.extent.z)
            plane.width = width
            plane.height = height

            // 3
            let x = CGFloat(planeAnchor.center.x)
            let y = CGFloat(planeAnchor.center.y)
            let z = CGFloat(planeAnchor.center.z)
            planeNode.position = SCNVector3(x, y, z)
        }
    }

I also recommend you in viewDidLoad to call the function configureLighting() for better user experience 我还建议您在viewDidLoad中调用函数configureLighting()以获得更好的用户体验

func configureLighting() {
        sceneView.autoenablesDefaultLighting = true
        sceneView.automaticallyUpdatesLighting = true
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM