4
votes

Complete swift beginner struggling to add nodes to scene on tap of a button.

I am aware I can use tap gesture to get the tap coordinates and perform a hit test and then place an object in 3D space where tapped. However I want to show a sphere or crosshair in the centre of device screen and when tap a button at the bottom of the screen have the same behaviour of obtaining the same information a tap gesture would give.(At least i think that is what I need to do here i'm not sure.)

After loading my scene I add a small Sphere to the child node of the camera point of view like this:

sphereNode = SCNNode(geometry: SCNSphere(radius: 0.020))
sphereNode?.position = SCNVector3Make(0, 0, -2)
sceneView.pointOfView?.addChildNode(sphereNode!)

This places the sphere in the centre of the screen slightly in front of the camera. As I move the device around the room the sphere stays in the middle as expected. I want to be able to tap a button then obtain the information that a tap gesture would give in order to perform a hit test and place a new sphere in the scene at that location. Unless there is another better way of doing this?

The behaviour I am looking for is very similar to that of the iOS measuring app. The measure point stays in the centre of the screen at all times, then on tapping add a new point is added.

1

1 Answers

2
votes

Your approach of using hitTest(_:types:) is the way to go. I think that the linked one, from ARSession, is the most straightforward.

Since you want to hit test from the center of the screen, and the CGPoint argument expected by hitTest(_:types:) is in normalized coordinate space, from (0.0, 0.0) to (1.0, 1.0), all you need to do is pass (0.5, 0.5).

Here is some code:

func buttonAction() {
  guard let currentFrame = session.currentFrame,
    let hitTest = currentFrame.hitTest(CGPoint(x: 0.5, y: 0.5), types: .featurePoint).last else {
    return
  }
  let anchor = ARAnchor(transform: hitTest.worldTransform)
  session.add(anchor: anchor)
}

After the anchor is added, you can add the node using ARSCNViewDelegate's method renderer(_:nodeFor:). Basically, this method is going to be called when you add an anchor to the session.

By the way, since it seems that you're using ARSCNView, you can access your AR session like this sceneView.session.