0

Is there a native way with SceneKit to find a node at a given position, e.g., (0,0,0), within a SCNView?

Assume a SCNView contains a SCNNode which acts as a layer for other SCNNodes. Is there a native way to find all the nodes at a specific position within the layer?

Reading the class docs, it seems like the only option is to create and maintain a custom data structure mapping positions to nodes.

But hopefully there's something native since this seems like a common problem.

If a custom data structure is required, would a dictionary be the most efficient way to maintain tabs on 10K nodes in Swift?

Crashalot
  • 33,605
  • 61
  • 269
  • 439

2 Answers2

2

a node conforms to the SCNBoundingVolume and so you can have a rough idea of whether a node "contains" the origin. You can also use -[SCNNode - hitTestWithSegmentFromPoint:toPoint:options:] with different options to refine your search.

mnuages
  • 13,049
  • 2
  • 23
  • 40
  • Thanks for the suggestion. So would you use `hitTestWithSegmentFromPoint` instead of `nodesInsideFrustumWithPointOfView` as Hal proposes? Note the nodes are stationary. – Crashalot May 01 '16 at 21:13
  • I like the idea of `SCNBoundingVolume` better than either `hitTestWithSegmentFromPoint` or `nodesInsideFrustumWithPointOfView` because you're working only with the model side (SCNNode) instead of involving a renderer. Do you need to do this offscreen? Note the bug mentioned in this answer from iOS 8/Yosemite days: http://stackoverflow.com/questions/29198636/using-scenekit-for-hittesting-not-returning-a-hit-with-scnnode – Hal Mueller May 02 '16 at 01:05
1

Although I've never tried it, it looks like SCNPhysicsWorld can help you do this. You'd need a physics body on each node you want to track or query.

You could place an invisible body at your target point, and wait for collision delegate callbacks.

There's also convexSweepTestWithShape(_ shape: SCNPhysicsShape, fromTransform from: SCNMatrix4, toTransform to: SCNMatrix4, options options: [String : AnyObject]?) -> [SCNPhysicsContact].

Another approach would be to use SCNSceneRenderer's nodesInsideFrustumWithPointOfView function, with an orthographic SCNCamera so that you can get a rectangular or cubic frustum.

In general with SceneKit, btw, check all of the applicable protocol references. Many of the common calls are on a protocol and not a class.

Hal Mueller
  • 7,019
  • 2
  • 24
  • 42
  • Thanks Hal! This seems like an interesting idea. Though If a SceneView contains 10K nodes would attaching a separate physics body be more efficient or just using a dictionary to map positions to nodes? – Crashalot May 01 '16 at 19:46
  • I think it would depend on whether they're moving, and on how deeply into your node hierarchy you need to map. For example, if you're mapping 20 spherish thingies, each with 5k nodes, you could use physics just for the top level spheres. Try it, measure, and blog about it! If they're stationary, then a dictionary, or geohash, or R-tree would probably do better. – Hal Mueller May 01 '16 at 20:00
  • Thanks! Yes, the nodes are stationary, but `nodesInsideFrustumWithPointOfView` seems like that's actually the best approach since it wouldn't requiring maintaining separate state. Thanks so much for your help. Your other answers on SO re SceneKit have been extremely helpful. – Crashalot May 01 '16 at 21:12