I have a question that about detecting touch in SceneKit. I have been able to find questions about how to detect when a certain object is touched but I need something a bit more specific. I need to be able to tell when a certain part of an object is touched. To explain a little better, I have a 3d model of a human and I need to be able to tell when say the head is touched or the leg is touched etc. If any further clarification is needed I would be glad to provide it, I'm just not quite sure how to accomplish this.
-
Possible duplicate of [identify face of a cube hit on touches began in Swift-Scene Kit](http://stackoverflow.com/questions/35153302/identify-face-of-a-cube-hit-on-touches-began-in-swift-scene-kit) – Hal Mueller Nov 08 '16 at 07:16
2 Answers
To expand on NicoS's answer: hit testing is the way to do this. But you actually have several possible options for identifying model parts in a hit test result, so you can choose the one that best fits your content creation pipeline.
As noted in other answers, if you can break your model up into separate models, each of which is hosted in the scene with its own node, you can use the
SCNHitTestResult.node
property to find out which node was clicked/tapped/grabbed.If you can't split the model completely, you may be able to split it into multiple parts that still live in the same asset/node. SceneKit calls these geometry elements, some authoring tools call them submeshes, low-level rendering code calls it a separate draw call with a separate index buffer, etc. When you have separate geometry elements (which are necessary for drawing one geometry with multiple materials on different parts of the geometry), you can identify them in hit-testing with the
SCNHitTestResult.geometryIndex
property. (This approach is used in the answer HalMueller linked to.)If you control the texture mapping data for the mesh, you can use
textureCoordinates(withMappingChannel:)
to get texture coordinates for the clicked point, then look them up in a texture image in which you've color-coded the ares of interest. (You can get a general overview for the theory behind this idea in this article, though the implementation isn't specific to SceneKit.)If your model is rigged for skeletal animation, you can use the
SCNHitTestResult.boneNode
property to get the bone most responsible for geometry deformation at the clicked point.
Hit testing is the way to go. But your 3D model needs to be adapted. You need to give the items that you want proper names in your favourite 3D editor. Then you can use the HitTest function on SCNSceneRenderer.
For example: a ray is casted from the position of your finger to the 3D model underneath the touch point. The hitTest function will give you an array of SCNHitResults. The first object in that array is the front most that is visible to the user. Then you can check if the node.name
has the name that you want to find.
You can find more information here: https://developer.apple.com/reference/scenekit/scnscenerenderer/1522929-hittest https://developer.apple.com/reference/scenekit/scnhittestresult

- 3,056
- 1
- 30
- 64