Reputation: 130
I'm trying to keep an SCNNode always one meter away from the front of the camera, and manipulate the node so that the X and Z axes are always parallel to the ground, while the node rotates around the Y-axis so that the node is always facing the camera.
The code below achieves my goal for the most part, but when turning more than 90˚ clockwise or counterclockwise, the node starts turning. How can I fix that?
override func viewDidLoad() {
super.viewDidLoad()
boxParent.position = (sceneView.pointOfView?.position)!
boxParent.orientation = (sceneView.pointOfView?.orientation)!
boxParent.eulerAngles = (sceneView.pointOfView?.eulerAngles)!
sceneView.scene.rootNode.addChildNode(boxParent)
boxOrigin.position = SCNVector3(0,0,-1)
boxParent.addChildNode(boxOrigin)
box = SCNNode(geometry: SCNBox(width: 0.5, height: 0.2, length: 0.3, chamferRadius: 0))
box.geometry?.firstMaterial?.diffuse.contents = UIColor.blue
box.position = SCNVector3(0,0,0)
boxOrigin.addChildNode(box)
}
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
boxParent.eulerAngles = (sceneView.pointOfView?.eulerAngles)!
boxParent.orientation = (sceneView.pointOfView?.orientation)!
boxParent.position = (sceneView.pointOfView?.position)!
box.position = boxOrigin.worldPosition
box.eulerAngles.y = (sceneView.pointOfView?.eulerAngles.y)!
print(box.eulerAngles)
sceneView.scene.rootNode.addChildNode(box)
}
Upvotes: 1
Views: 770
Reputation: 58103
You're simultaneously using two types of rotation. It's wrong!
boxParent.orientation = (sceneView.pointOfView?.orientation)! //quaternion
This variable uses the node’s orientation, expressed as quaternion
(4 components: x, y, z, w).
boxParent.eulerAngles = (sceneView.pointOfView?.eulerAngles)!
The node’s rotation, expressed as pitch, yaw, and roll angles, in radians (3 components: x, y, z).
You need to decide which var you'll be using:
orientation
oreulerAngles
. I suppose you'll choose orientation.
Read this useful article and this one about Quaternions
and what a Gimbal Lock
is.
Also, use SCNLookAtConstraint
object (node's negative z-axis points toward the constraint's target node) or SCNBillboardConstraint
object (automatically adjusts a node's orientation so that its local z-axis always points toward the node's pointOfView) for automatically adjusting a node’s orientation, so you camera'll be always pointing toward another node.
Upvotes: 1