1
votes

I'm creating a navigational application that will use augmented reality to help users navigate to specified locations.

I want to have a SCNNode (an arrow, in this case) positioned in front of the device and slightly below the y-axis. The arrow will be oriented towards the location the user is navigating to. As the user walks around, the arrow will rotate about the y-axis to stay pointing towards the navigation location.

In order for my arrow to be oriented towards a real-world location, I had to set ARWorldTrackingConfiguration.worldAlignment = .gravityAndHeading, but by doing so I can no longer place my SCNNode relative to the device's camera.

Is there a way to have my SCNNode always in front of my camera, but also oriented towards a real-world location?

My current code:

let arrowScene = SCNScene(named: "art.scnassets/arrow.dae")!
let arrowNode = arrowScene.rootNode.childNode(withName: "arrow", recursively: true)!

let loc = locationManager.location?.coordinate
let bearing = loc?.calculateBearing(to: CLLocationCoordinate2D(latitude: 36.971542, longitude: -82.558492))

arrowNode.position = SCNVector3(0.0, -1.0, 1.5)

arrowNode.transform = SCNMatrix4Mult(arrowNode.transform, SCNMatrix4MakeRotation(Float(bearing!), 0.0, 1.0, 0.0))

sceneView.scene = arrowScene

enter image description here

1

1 Answers

1
votes

This worked out for me:

First, get the rotation matrix of the camera:

let rotate = simd_float4x4(SCNMatrix4MakeRotation(sceneView.session.currentFrame!.camera.eulerAngles.y, 0, 1, 0))

Then, combine the matrices:

let rotateTransform = simd_mul(r.worldTransform, arrowRotationTransform)

Lastly, apply a transform to your node, casting as SCNMatrix4:

node.transform = SCNMatrix4(rotateTransform)

Hope that helps!!