在 ARKit 中检测 SCNNode 上的触摸 [英] Detect touch on SCNNode in ARKit

查看:26
本文介绍了在 ARKit 中检测 SCNNode 上的触摸的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 ARKit 1.5 beta 中已识别图像的位置放置了一个 SCNNode(一个平面).我想在点击飞机时向控制台打印一条消息.到目前为止,我有这个代码:

I have placed a SCNNode (a plane) at the location of a recognized image in ARKit 1.5 beta. I would like to print a message to the console when the plane is tapped on. So far I have this code:

// MARK: - ARSCNViewDelegate (Image detection results)
    /// - Tag: ARImageAnchor-Visualizing
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

        guard let imageAnchor = anchor as? ARImageAnchor else { return }
        let referenceImage = imageAnchor.referenceImage
        updateQueue.async {

            // Create a plane to visualize the initial position of the detected image.
            let plane = SCNPlane(width: referenceImage.physicalSize.width,
                                 height: referenceImage.physicalSize.height)
            let planeNode = SCNNode(geometry: plane)
            planeNode.opacity = 0.25

            /*
             `SCNPlane` is vertically oriented in its local coordinate space, but
             `ARImageAnchor` assumes the image is horizontal in its local space, so
             rotate the plane to match.
             */
            planeNode.eulerAngles.x = -.pi / 2

            /*
             Image anchors are not tracked after initial detection, so create an
             animation that limits the duration for which the plane visualization appears.
             */
            //planeNode.runAction(self.imageHighlightAction)

            // Add the plane visualization to the scene.
            node.addChildNode(planeNode)
        }

        DispatchQueue.main.async {
            let imageName = referenceImage.name ?? ""
            self.statusViewController.cancelAllScheduledMessages()
            self.statusViewController.showMessage("Detected image "\(imageName)"")
        }
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first as! UITouch
        if(touch.view == self.sceneView){
            print("touch working")
            let viewTouchLocation:CGPoint = touch.location(in: sceneView)
            guard let result = sceneView.hitTest(viewTouchLocation, options: nil).first else {
                return
            }
            if let planeNode = planeNode, planeNode == result.node {
                print("match")
            }

        }
    }

但我在这一行收到未解析的标识符"错误:if let planeNode = planeNode, planeNode == result.node {,我理解这是因为planeNode 是在Renderer 函数中定义的以上并且不在正确的范围内.我的问题是如何解决这个问题,因为我不相信我可以在 Renderer 中返回值,也不能将 touchesBegan 函数放在 Renderer 函数中,因此它在正确的范围内.谁能给我任何关于如何解决这个问题的想法?谢谢!

But I'm getting an 'unresolved identifier' error on this line: if let planeNode = planeNode, planeNode == result.node {, which I understand because planeNode is defined in the Renderer function above and is not in the right scope. My question is how to fix this, because I dont believe I can return the value in Renderer, nor can I put the touchesBegan function in the Renderer function so its in the right scope. Can anyone give me any ideas on how to fix this? Thanks!

推荐答案

为了解决这个问题,在你的ViewController中声明一个全局变量

To solve this problem declare a global variable in your ViewController

class ViewController: UIViewController, ARSCNViewDelegate {

    @IBOutlet var sceneView: ARSCNView!

    var planeNode : SCNNode? = nil

    .....

}

然后使用刚刚声明的planeNode变量并将其分配给渲染器方法中的实际planeNode

Then use the planeNode variable just declared and assign it to your actual planeNode in the renderer method

func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {

     .........

     let planeNode = SCNNode(geometry: plane)
     self.planeNode = planeNode
}

这样你就可以从类内的任何地方访问planeNode

This way you can access the planeNode from anywhere inside the class

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first as! UITouch
    if(touch.view == self.sceneView){
        print("touch working")
        let viewTouchLocation:CGPoint = touch.location(in: sceneView)
        guard let result = sceneView.hitTest(viewTouchLocation, options: nil).first else {
            return
        }
        if let planeNode = planeNode, planeNode == result.node {
            print("match")
        }

    }
}

这篇关于在 ARKit 中检测 SCNNode 上的触摸的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆