SceneKit - Ignore touches on an SCNNode in the foreground and transfer touch to a background node

65 views Asked by At

I am trying to make an app where users can measure distances on an ARSCNView. I have a scenario where there are 2 SCNNodes on top of each other. Node1 is always at the front because of its depth information. Node2 however is useful for measuring and getting accurate measurements. I would like to ignore touches on node1 and only get the location of touch on node2.

When I hide node1, the touches are properly recognized on node2. However, I still need node1 to be visible to the user.

I tried to change the renderingOrder and making sure that node2 is added to the rootNode after node1 is, but was of no success.

I also verified the hitTest array on tapping on a point, only the one hitTest on node1 is recognized and present in the array. So I'm not able to select a different hitTestResult either.

Further info: Node1 is a huge node which occupies a large space and node2 is formed from multiple child nodes.

2

There are 2 answers

0
ZAY On BEST ANSWER

You could probably do this using different Bitmasks (the categoryBitmask of the SCNNode) on which perform the hitTestResult.

Or if you have physicsBodies involved on the SCNNodes, you can do a rayTest to its physics categoryBitmasks. (scene.physicsWorld.rayTestWithSegment)

0
Chandana On

Thanks @ZAY for your answer. It worked perfectly.

I got further help from this answer.

What I did:

struct NodeType: OptionSet {
  let rawValue: Int

  static let `default` = NodeType(rawValue: 1)
  static let userInteraction = NodeType(rawValue: 4)
}

My foreground node has a default category bitmask of 1. I did not specify anything.

To my background node, I assigned bitmask as:

node.categoryBitMask = NodeType.userInteraction.rawValue

When performing hitTest, I provided this bitMask as an option:

let touchPosition = gesture.location(in: arSceneView)
let hitResults = arSceneView.hitTest(touchPosition, options: [SCNHitTestOption.categoryBitMask: NodeType.userInteraction.rawValue])

Voila, my foreground node is ignored and the background node gets the hitTest interaction.