swift – 如何使用ARKit检测触摸并显示新的SCNPlane?
| 
                         
 现在,当检测到卡时,我能够显示不同的SCNPlane.在显示SCNPlanes之后,用户触摸任何平面以显示新的SCNPlane.但是现在触摸工作正常,但新的SCNPlane没有显示. 
  
  
这是我尝试过的代码: var cake_1_PlaneNode : SCNNode? = nil
func renderer(_ renderer: SCNSceneRenderer,didAdd node: SCNNode,for anchor: ARAnchor) {
    guard let imageAnchor = anchor as? ARImageAnchor else { return }
    if let imageName  = imageAnchor.referenceImage.name {            
        print(imageName)
        if imageName == "menu" {
            // Check To See The Detected Size Of Our menu Card (Should By 5cm*3cm)
            let menuCardWidth = imageAnchor.referenceImage.physicalSize.width
            let menuCardHeight =  imageAnchor.referenceImage.physicalSize.height
            print(
                """
                We Have Detected menu Card With Name (imageName)
                (imageName)'s Width Is (menuCardWidth)
                (imageName)'s Height Is (menuCardHeight)
                """)
            //raspberry
            //cake 1
            let cake_1_Plane = SCNPlane(width: 0.045,height: 0.045)
            cake_1_Plane.firstMaterial?.diffuse.contents = UIImage(named: "france")
            cake_1_Plane.cornerRadius = 0.01
            let cake_1_PlaneNode = SCNNode(geometry: cake_1_Plane)
            self.cake_1_PlaneNode = cake_1_PlaneNode
            cake_1_PlaneNode.eulerAngles.x = -.pi/2
            cake_1_PlaneNode.runAction(SCNAction.moveBy(x: 0.15,y: 0,z: -0.125,duration: 0.75))
            node.addChildNode(cake_1_PlaneNode)
            self.sceneView.scene.rootNode.addChildNode(node)                
        }  
   }       
   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 = cake_1_PlaneNode,cake_1_PlaneNode == result.node{
            print("match")
            cake_1() 
        }
    }
}
func cake_1() {
    let plane = SCNPlane(width: 0.15,height: 0.15)
    plane.firstMaterial?.diffuse.contents = UIColor.black.withAlphaComponent(0.75)
    let planeNodee = SCNNode(geometry: plane)
    planeNodee.eulerAngles.x = -.pi / 2
    planeNodee.runAction(SCNAction.moveBy(x: 0.21,z: 0,duration: 0))
} //cake_1 
 点击此链接:Detect touch on SCNNode in ARKit. 
 查看代码,我可以看到几个问题(更不用说变量和方法的命名约定). 
  
                          首先,您正在创建一个您已声明的全局变量: var cake_1_PlaneNode : SCNNode? = nil 但是,在yourDelegate回调中为cake_1_PlaneNode使用本地变量和全局变量: let cake_1_PlaneNode = SCNNode(geometry: cake_1_Plane) self.cake_1_PlaneNode = cake_1_PlaneNode 这应该只是这样读: self.cake_1_PlaneNode = SCNNode(geometry: cake_1_Plane) 其次,您将cake_1_PlaneNode添加到ARSCNView的rootNode而不是您检测到的ARImageAnchor,这可能是您不想做的事情,因为当检测到ARAnchor时: 
 因此,这种方法(除非你真的想这样做)是不必要的. 剩下的问题在于你的cake_1函数本身. 首先,您实际上并没有将planeNodee添加到sceneHierachy中. 由于您尚未指定是否应将新初始化的planeNode直接添加到ARSCNView或作为cake_1_planeNode的childNode,因此您的函数应包括以下内容之一: self.sceneView.scene.rootNode.addChildNode(planeNodee) self.cake_1_planeNode.addChildNode(planeNodee) 此外,可能还没有必要旋转您的planeNodee,因为默认情况下SCNPlane是垂直渲染的. 由于您没有规定放置内容的位置,因此可能不需要使用-.pi / 2,因为这可能使其几乎看不见肉眼. 另一个问题也可能导致您在实际添加节点时没有看到您的节点是Z位置. 如果您在同一位置设置2个节点,您可能会遇到一个称为Z-fighting的问题(您可以阅读更多关于here的信息).因此,您可能应该在添加节点时稍微向前移动添加的节点,例如SCNVector3(0,0.001)来解释这一点. 基于所有这些要点,我在下面提供了一个完整的工作和评论示例: import UIKit
import ARKit
//-------------------------
//MARK: - ARSCNViewDelegate
//-------------------------
extension ViewController: ARSCNViewDelegate {
    func renderer(_ renderer: SCNSceneRenderer,for anchor: ARAnchor) {
        //1. Check We Have An ARImageAnchor,Then Get It's Reference Image & Name
        guard let imageAnchor = anchor as? ARImageAnchor else { return }
        let detectedTarget = imageAnchor.referenceImage
        guard let detectedTargetName = detectedTarget.name  else { return }
        //2. If We Have Detected Our Virtual Menu Then Add The CakeOnePlane
        if detectedTargetName == "cakeMenu" {
            let cakeOnePlaneGeometry = SCNPlane(width: 0.045,height: 0.045)
            cakeOnePlaneGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
            cakeOnePlaneGeometry.cornerRadius = 0.01
            let cakeOnPlaneNode = SCNNode(geometry: cakeOnePlaneGeometry)
            cakeOnPlaneNode.eulerAngles.x = -.pi/2
            //3. To Allow Us To Easily Keep Track Our Our Currently Added Node We Will Assign It A Unique Name
            cakeOnPlaneNode.name = "Strawberry Cake"
            node.addChildNode(cakeOnPlaneNode)
            cakeOnPlaneNode.runAction(SCNAction.moveBy(x: 0.15,duration: 0.75))
        }
    }
}
class ViewController: UIViewController {
    @IBOutlet var augmentedRealityView: ARSCNView!
    let augmentedRealitySession = ARSession()
    let configuration = ARWorldTrackingConfiguration()
    //------------------
    //MARK: - Life Cycle
    //------------------
    override func viewDidLoad() {
        super.viewDidLoad()
        setupARSession()
    }
    //-----------------
    //MARK: - ARSession
    //-----------------
    /// Runs The ARSession
    func setupARSession(){
        //1. Load Our Detection Images
        guard let detectionImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources",bundle: nil) else { return }
        //2. Configure & Run Our ARSession
        augmentedRealityView.session = augmentedRealitySession
        augmentedRealityView.delegate = self
        configuration.detectionImages = detectionImages
        augmentedRealitySession.run(configuration,options: [.resetTracking,.removeExistingAnchors])
    }
    //--------------------
    //MARK: - Interaction
    //--------------------
    override func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?) {
        //1. Get The Current Touch Location & Perform An ARSCNHitTest To Check For Any Hit SCNNode's
        guard let currentTouchLocation = touches.first?.location(in: self.augmentedRealityView),let hitTestNode = self.augmentedRealityView.hitTest(currentTouchLocation,options: nil).first?.node else { return }
        //2. If We Have Hit Our Strawberry Cake Then We Call Our makeCakeOnNode Function
        if let cakeID = hitTestNode.name,cakeID == "Strawberry Cake"{
            makeCakeOnNode(hitTestNode)
        }
    }
    /// Adds An SCNPlane To A Detected Cake Target
    ///
    /// - Parameter node: SCNNode
    func makeCakeOnNode(_ node: SCNNode){
        let planeGeometry = SCNPlane(width: 0.15,height: 0.15)
        planeGeometry.firstMaterial?.diffuse.contents = UIColor.black.withAlphaComponent(0.75)
        let planeNode = SCNNode(geometry: planeGeometry)
        planeNode.position = SCNVector3(0,0.001)
        planeNode.runAction(SCNAction.moveBy(x: 0.21,duration: 0))
        node.addChildNode(planeNode)
    }
} 
 这在我的设备上产生以下内容: 对于您的信息,这似乎表明您放置内容的计算是关闭的(除非当然这是期望的结果). 正如您所看到的,所有内容都正确呈现,但是这些内容的间距非常大,因此您可能需要稍微平移设备,以便在进一步测试和开发时看到它们. 希望能帮助到你… (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!  | 
                  
