3

I am trying to attach an object in front of the camera, but the issue is that it is always in relation to the initial camera direction. How can I adjust/get the SCNVector3 position to place the object in front, even if the direction of the camera is up or down?

This is how I do it now:

let ballShape = SCNSphere(radius: 0.03)
let ballNode = SCNNode(geometry: ballShape)
let viewPosition = sceneView.pointOfView!.position
ballNode.position = SCNVector3Make(viewPosition.x, viewPosition.y, viewPosition.z - 0.4)
sceneView.scene.rootNode.addChildNode(ballNode)
Tal Zion
  • 6,308
  • 3
  • 50
  • 73

1 Answers1

3

Edited to better answer the question now that it's clarified in a comment

New Answer:

You are using only the position of the camera, so if the camera is rotated, it doesn't affect the ball.

What you can do is get the transform matrix of the ball and multiply it by the transform matrix of the camera, that way the ball position will be relative to the full transformation of the camera, including rotation.

e.g.

let ballShape = SCNSphere(radius: 0.03)
let ballNode = SCNNode(geometry: ballShape)
ballNode.position = SCNVector3Make(0.0, 0.0, -0.4)
let ballMatrix = ballNode.transform
let cameraMatrix = sceneView.pointOfView!.transform
let newBallMatrix = SCNMatrix4Mult(ballMatrix, cameraMatrix)
ballNode.transform = newBallMatrix
sceneView.scene.rootNode.addChildNode(ballNode)

Or if you only want the SCNVector3 position, to answer exactly to your question (this way the ball will not rotate):

...
let newBallMatrix = SCNMatrix4Mult(ballMatrix, cameraMatrix)
let newBallPosition = SCNVector3Make(newBallMatrix.m41, newBallMatrix.m42, newBallMatrix.m43)
ballNode.position = newBallPosition
sceneView.scene.rootNode.addChildNode(ballNode)

Old Answer:

You are using only the position of the camera, so when the camera rotates, it doesn't affect the ball.

SceneKit uses a hierarchy of nodes, so when a node is "child" of another node, it follows the position, rotation and scale of its "parent". The proper way of attaching an object to another object, in this case the camera, is to make it "child" of the camera.

Then, when you set the position, rotation or any other aspect of the transform of the "child" node, you are setting it relative to its parent. So if you set the position to SCNVector3Make(0.0, 0.0, -0.4), it's translated -0.4 units in Z on top of its "parent" translation.

So to make what you want, it should be:

let ballShape = SCNSphere(radius: 0.03)
let ballNode = SCNNode(geometry: ballShape)
ballNode.position = SCNVector3Make(0.0, 0.0, -0.4)
let cameraNode = sceneView.pointOfView
cameraNode?.addChildNode(ballNode)

This way, when the camera rotates, the ball follows exactly its rotation, but separated -0.4 units from the camera.

ciclopez
  • 128
  • 1
  • 8
  • 1
    Thanks @ciclopez but this is not what I am looking for. I want that the ball will keep it's position static, but when added, it is added in front of the current camera position, after, the camera can move. Same to my implementation, but when the camera is looking down, it would add the node relative to the direction but will stay there. – Tal Zion Jan 12 '19 at 22:06