0

I have an ARSceneView and I use the detectionImages to find a plane so I can add nodes based on the Image that I detected.

My Issue is that all the time the view is adding an invisible plane node above the nodes that I have added as subnodes in the "node of my Image" and when I add a TapGestureRecognizer to the sceneView I can't detect the node because it detects the plane. Sometimes it works, but when it adds the plane it doesn't work.

When the plane is on scene my nodes are these

I want my nodes to be like this..

▿ 3 elements - 0 : | no child> - 1 : SCNNode: 0x1c41f4100 | light= - 2 : SCNNode: 0x1c43e1000 'DetectableChildrenParent' pos(-0.009494 -0.081575 -0.360098) rot(0.997592 -0.060896 0.033189 1.335512) | 2 children>

and my 2 children to be the detectable nodes only..

but it always is like this

▿ 4 elements - 0 : SCNNode: 0x1c01fcc00 pos(-0.093724 0.119850 -0.060124) rot(-0.981372 0.172364 -0.084866 0.457864) scale(1.000000 1.000000 1.000000) | camera= | no child> - 1 : SCNNode: 0x1c01fc200 | light= | no child> - 2 : SCNNode: 0x1c01fd100 'DetectableChildrenParent' pos(-0.149971 0.050361 -0.365586) rot(0.996908 0.061535 -0.048872 1.379775) scale(1.000000 1.000000 1.000000) | 2 children> - 3 : SCNNode: 0x1c01f9f00 | geometry= | no child>

and it always detect the last node.

My code to detect is this

@objc func addNodeToScene(withGestureRecognizer recognizer: UIGestureRecognizer) {
            let tapLocation = recognizer.location(in: self.sceneView)
            let hitTestResults = sceneView.hitTest(tapLocation)
            if let node = hitTestResults.first?.node {
                    print(node.name ?? "")
            }
    }

How can I run the hit test to check only the children of the DetectableChildrenParent?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Vasilis D.
  • 1,416
  • 13
  • 21

1 Answers1

4

Assuming I have interpreted your question correctly, what you are looking for is the childNodes property of the SCNHitTestResult Node which refers to:

An array of the node’s children in the scene graph hierarchy.

As such I believe you can try something like this:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    //1. Get The Current Touch Location
    guard let currentTouchLocation = touches.first?.location(in: self.augmentedRealityView),

        //2. Get The Tapped Node From An SCNHitTest
        let hitTestResultNode = self.augmentedRealityView.hitTest(currentTouchLocation, options: nil).first?.node else { return }

    //3. Loop Through The ChildNodes
    for node in hitTestResultNode.childNodes{

        //4. If The Node Has A Name Then Print It Out
        if let validName = node.name{
             print("Node\(validName) Is A Child Node Of \(hitTestResultNode)")
        }

    }

}

Alternatively instead of looking for the 1st result of the SCNHitTest you could try by looking for the last one instead e.g:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    //1. Get The Current Touch Location
    guard let currentTouchLocation = touches.first?.location(in: self.augmentedRealityView),

        //2. Get The Tapped Node From An SCNHitTest
        let hitTestResultNode = self.augmentedRealityView.hitTest(currentTouchLocation, options: nil).last?.node else { return }

    //3. Loop Through The ChildNodes
    for node in hitTestResultNode.childNodes{

        //4. If The Node Has A Name Then Print It Out
        if let validName = node.name{
             print("Node\(validName) Is A Child Node Of \(hitTestResultNode)")
        }

    }

}

If you are looking for the children of a specific SCNNode you use the following:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    //1. Get The Current Touch Location
    guard let currentTouchLocation = touches.first?.location(in: self.augmentedRealityView),

    //2. Get The Tapped Node From An SCNHitTest
    let hitTestResultNode = self.augmentedRealityView.hitTest(currentTouchLocation, options: nil).first?.node else { return }

    //3. If The Name Of The Nodes Is Equal To DetectableChildrenParent Then Get The Children
    if hitTestResultNode.name == "DetectableChildrenParent"{

        let childNodes = hitTestResultNode.childNodes

        print(childNodes)
    }

}

Or alternatively you can be to simply loop through the SCNHitTestResults like so:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    //1. Get The Current Touch Location
    guard let currentTouchLocation = touches.first?.location(in: self.augmentedRealityView) else { return }

    //2. Get The Results Of The SCNHitTest
    let hitTestResults = self.augmentedRealityView.hitTest(currentTouchLocation, options: nil)


    //3. Loop Through Them And Handle The Result
    for result in hitTestResults{

        print(result.node)
        print(result.node.childNodes)
    }


}

Hope it helps...

BlackMirrorz
  • 7,217
  • 2
  • 20
  • 31
  • No it's the same thing, because the invisible node 3 SCNNode: 0x1c01f9f00 | geometry= | no child> goes above the 2 : SCNNode: 0x1c01fd100 'DetectableChildrenParent' pos(-0.149971 0.050361 -0.365586) rot(0.996908 0.061535 -0.048872 1.379775) scale(1.000000 1.000000 1.000000) | 2 children> it detects as node in hitTestResultNode that node but thank you – Vasilis D. Apr 30 '18 at 12:32
  • Is the nodes name "DetectableChildrenParent"? – BlackMirrorz Apr 30 '18 at 12:34
  • No the node that has the children that I am trying to detect name is "DetectableChildrenParent" and it has 2 child nodes. These nodes I am trying to detect and only these. – Vasilis D. Apr 30 '18 at 12:36
  • Thanks for the try but it's exactly the same because in the line let hitTestResultNode = self.augmentedRealityView.hitTest(currentTouchLocation, options: nil).first?.node else { return } it detects the node 3 SCNNode: 0x1c01f9f00 | geometry= | no child> so then the name doesn't matter – Vasilis D. Apr 30 '18 at 12:43
  • 1
    try let hitTestResultNode = self.augmentedRealityView.hitTest(currentTouchLocation, options: nil).last – BlackMirrorz Apr 30 '18 at 12:44
  • Only thing i had to do is to add one more check to check to last as you said me so edit your answer to mark it correct. Thank you – Vasilis D. Apr 30 '18 at 12:55
  • Updated again :) – BlackMirrorz Apr 30 '18 at 13:08
  • My hit test result's node's name is nil. Any idea why? the node has valid name in ARSCNView. – Jamil Aug 05 '20 at 11:55