Reputation: 7873
I want to add a node to my scene, keeping a position in relation to the camera, but keeping the orientation/rotation of the scene. Where I'm up to so far...
When I tap the screen, I add an anchor to my scene, with a transform equal to the camera's transform. Then in didUpdateNode
, which is when the anchor node has its' positional information setup, I add a child node containing a model, which has position.z = -0.5
. The model node is added to the scene directly in front of the camera, and mirrors the rotational properties of the camera. With the phone tilted downwards and at an angle, this might look like so:
The model node, affected by the rotational data of the anchor node, is rotated in the same way as the camera. This particular model appears on its side - I'm not concerned about that, it's just a placeholder. Also ignore the red button at the top, that was for debugging.
So far, so good.
What I want to happen instead of this is for the rotational information to essentially be "reset", so it instead appears at the same height as my camera, and facing a default face-forward position. And if I were to rotate the camera differently and move around the room, additional models would be added at differing positions, but still at the same height and with the same orientation.
That might look something like this. Imagine that I've just tapped the screen to add the object, and it appears at a standard height, and rotation relevant to the scene, rather than the camera.
I've tried playing around with the node's eulerAngles
, rotation
and orientation
properties but can't get this to work satisfactorily. Here's the code I have so far.. I've created a blank scene, and I'm using ship.scn
from the standard SceneKit project as the model:
class ViewController: UIViewController, ARSCNViewDelegate {
@IBOutlet var sceneView: ARSCNView!
var anchors = [ARAnchor]()
override func viewDidLoad() {
super.viewDidLoad()
// Set the view's delegate
sceneView.delegate = self
// Show statistics such as fps and timing information
sceneView.showsStatistics = true
// Create a new scene
let scene = SCNScene(named: "scene.scn")!
// Set the scene to the view
sceneView.scene = scene
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Create a session configuration
let configuration = ARWorldTrackingSessionConfiguration()
configuration.planeDetection = .horizontal
// Run the view's session
sceneView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Pause the view's session
sceneView.session.pause()
}
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
if anchors.contains(anchor) {
// Create a new scene
let scene = SCNScene(named: "art.scnassets/ship.scn")!
let shipNode = scene.rootNode.childNode(withName: "ship", recursively: true)!
shipNode.position.z = -5
node.addChildNode(shipNode)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
if let currentFrame = sceneView.session.currentFrame {
let translation = matrix_identity_float4x4
let transform = simd_mul(currentFrame.camera.transform, translation)
let anchor = ARAnchor(transform: transform)
anchors.append(anchor)
sceneView.session.add(anchor: anchor)
}
}
}
}
Upvotes: 1
Views: 4377
Reputation: 491
Am I missing something or do you just want each model to have the same orientation, irrespective of camera orientation?
In which case can you just set each models orientation to be the same as a node added when the session began running?
I.e when the session begins you add a node to the scene (visible or hidden), save its orientation, then use that again later on?
Upvotes: 0