【问题标题】:How to identify if user clicks on object that has been shown on screen using ARKit - swift如何识别用户是否点击了使用 ARKit 显示在屏幕上的对象 - swift
【发布时间】:2018-07-01 09:29:36
【问题描述】:

我是一个新的iOS编程。我想构建一个允许用户单击屏幕上显示的特定对象的应用程序。我将addGestureRecognizer 用于已显示的对象,以识别是否已单击用户,然后我只想将另一个对象添加到屏幕。

这是我到目前为止所做的

objpizza = make2dNode(image:#imageLiteral(resourceName: "pizza"),width: 0.07,height: 0.07)
    objpizza.position = SCNVector3(0,0,-0.2)
    objpizza.name = "none"

    self.arView.addGestureRecognizer(UIGestureRecognizer(target: self, action: #selector(selectObject)))
    arView.scene.rootNode.addChildNode(objpizza)

这里是make2dNode函数只是调整对象

func make2dNode(image: UIImage, width: CGFloat = 0.1, height: CGFloat = 0.1) -> SCNNode {
    let plane = SCNPlane(width: width, height: height)
    plane.firstMaterial!.diffuse.contents = image
    let node = SCNNode(geometry: plane)
    node.constraints = [SCNBillboardConstraint()]
    return node
}

这是我在self.arView.addGestureRecognizer(UIGestureRecognizer(target: self, action: #selector(selectObject))) 中实现时从未调用过的函数

@objc func selectObject() {

    print("Image has been selected")
}

【问题讨论】:

    标签: swift uigesturerecognizer arkit iosdeployment


    【解决方案1】:

    检测对SCNNode 的触摸需要的不仅仅是将UITapGestureRecogniser 添加到您的视图中。

    为了检测你触摸了哪个 SCNNode,你需要使用一个 SCNHitTest(结合你的gestureRecognizer),它是:

    寻找位于指定位置的场景元素的过程 点,或沿指定的线段(或射线)。

    SCNHitTest 寻找:

    沿您指定的射线的SCNGeometry 对象。对于每个路口 在射线和几何体之间,SceneKit 创建一个命中测试结果 提供有关包含 SCNNode 对象的信息 几何图形和几何图形上的交点位置 表面。

    好吧,你可能会想,但这在我的情况下实际上是如何工作的?

    好吧,让我们首先创建一个带有 SCNSphere 几何图形的 SCNNode 并将其添加到我们的场景中。

    //1. Create An SCNNode With An SCNSphere Geometry
    let nodeOneGeometry = SCNSphere(radius: 0.2)
    
    //2. Set It's Colour To Cyan
    nodeOneGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
    
    //3. Assign The Geometry To The Node
    nodeOne = SCNNode(geometry: nodeOneGeometry)
    
    //4. Assign A Name For Our Node
    nodeOne.name = "Node One"
    
    //5. Position It & Add It To Our ARSCNView
    nodeOne.position = SCNVector3(0, 0, -1.5)
    augmentedRealityView.scene.rootNode.addChildNode(nodeOne)
    

    您会注意到,我已经为我们的 SCNNode 分配了一个名称,这使得跟踪它(例如通过 hitTest 识别它)变得更加容易。

    现在我们已将 SCNNode 添加到层次结构中,让我们像这样创建一个UITapGestureRecognizer

    //1. Create A UITapGestureRecognizer & Add It To Our MainView
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(checkNodeHit(_:)))
    tapGesture.numberOfTapsRequired = 1
    self.view.addGestureRecognizer(tapGesture)
    

    现在我们已经完成了创建 checkNodeHit 函数所需的所有设置,该函数将检测用户点击了哪个节点:

    /// Runs An SCNHitTest To Check If An SCNNode Has Been Hit
    ///
    /// - Parameter gesture: UITapGestureRecognizer
    @objc func checkNodeHit(_ gesture: UITapGestureRecognizer){
    
        //1. Get The Current Touch Location In The View
        let currentTouchLocation = gesture.location(in: self.augmentedRealityView)
    
        //2. Perform An SCNHitTest To Determine If We Have Hit An SCNNode
        guard let hitTestNode = self.augmentedRealityView.hitTest(currentTouchLocation, options: nil).first?.node else { return }
    
        if hitTestNode.name == "Node One"{
    
            print("The User Has Successfuly Tapped On \(hitTestNode.name!)")
    
        }
    }
    

    现在,如果您想在用户点击的位置放置一个 SCNNode,则必须使用 ARSCNHitTest 来代替,它提供:

    关于通过检查一个点找到的真实世界表面的信息 AR 会话的设备摄像头视图。

    通过执行此操作,我们可以使用结果的worldTransform 属性将虚拟内容放置在该位置。

    worldTransform 是:

    命中测试结果相对于 世界坐标系。

    ARKit 中的定位可以像这样轻松可视化:

    再次让我们看看如何使用它来放置虚拟对象:

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    
        //1. Get The Current Touch Location In Our ARSCNView & Perform An ARSCNHitTest For Any Viable Feature Points
        guard let currentTouchLocation = touches.first?.location(in: self.augmentedRealityView),
              let hitTest = self.augmentedRealityView.hitTest(currentTouchLocation, types: .featurePoint).first else { return }
    
        //2. Get The World Transform From The HitTest & Get The Positional Data From The Matrix (3rd Column)
        let worldPositionFromTouch = hitTest.worldTransform.columns.3
    
        //3. Create An SCNNode At The Touch Location
        let boxNode = SCNNode()
        let boxGeometry = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
        boxGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
        boxNode.geometry = boxGeometry
        boxNode.position = SCNVector3(worldPositionFromTouch.x, worldPositionFromTouch.y, worldPositionFromTouch.z)
    
        //4. Add It To The Scene Hierachy
        self.augmentedRealityView.scene.rootNode.addChildNode(boxNode)
    
    }
    

    希望对你有帮助...

    【讨论】:

    • 非常感谢您抽出宝贵时间来解释这些精彩而有用的内容。这对我和我即将到来的项目真的很有帮助。
    【解决方案2】:

    你需要实现

    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTap(_:)))
    arView.addGestureRecognizer(tapGesture)
    

    函数判断用户是否被点击

    @obj func didTap(_ gesture: UITabGestureRecognizer){ 
      object2 = make2Node(image: nameOfimage, width: 0.07, height: 0.07)
      object2.position = SCNVector(0,0,0.2)
      arView.scene.rootNode.addChildNode(object2)
    

    享受编码吧。

    【讨论】:

    • 哇,这就是我在等的!谢谢你,兄弟!这个对我有用 :) 。你帮助逃脱了项目的最后期限。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-29
    • 2019-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多