I have a basic 3d Interactive globe built with swift and SceneKit. When the view launches, the camera is pointing towards Africa. I want to rotate and move the camera to point at Oregon, United States. I have the correct SCNVector3 for the position of Oregon, but my function incorrectly moves the camera. How can I compute the rotation to accurately move the camera to any SCNVector3 position?
My calculations below are wrong. I'm assuming you have to take into account the camera's current position and use that to compute the rotation and movement to the new position.
public var earthNode: SCNNode!
internal var sceneView : SCNView!
private var cameraNode: SCNNode!
func centerCameraOnDot(dotPosition: SCNVector3) {
let targetPhi = atan2(dotPosition.x, dotPosition.z)
let targetTheta = asin(dotPosition.y / dotPosition.length())
// Convert spherical coordinates back to Cartesian
let newX = 1 * sin(targetTheta) * sin(targetPhi)
let newY = 1 * cos(targetTheta)
let newZ = 1 * sin(targetTheta) * cos(targetPhi)
let fixedDistance: Float = 6.0
let newCameraPosition = SCNVector3(newX, newY, newZ).normalized().scaled(to: fixedDistance)
let moveAction = SCNAction.move(to: newCameraPosition, duration: 0.8)
// Create additional actions as needed
let rotateAction = SCNAction.rotateBy(x: 0, y: 0, z: 0, duration: 0.5)
// Create an array of actions
let sequenceAction = SCNAction.sequence([rotateAction])
// Run the sequence action on the cameraNode
cameraNode.runAction(sequenceAction)
}
You would need to adjust both the position and the orientation of the camera. Your current approach seems to correctly calculate the new position, but does not seem to properly handle the camera's rotation.
A modified version of your
centerCameraOnDotfunction would be:That code first calculates the new position of the camera as you did, but then, instead of manually rotating the camera, it uses a
SCNLookAtConstraint. That constraint automatically adjusts the camera's orientation to always look at the target node (in your case, the Earth node).And the camera's position is updated before applying the constraint to make sure it points from the correct location.
That assumes that your
earthNodeis correctly positioned at the center of your globe model. IfearthNodeis not at the center, you might need to create a separate node at the globe's center and use it for theSCNLookAtConstraint.The
SCNLookAtConstraintshould make the camera look directly at the target, but if the target is not at the center of the camera's view, this could be due to the initial orientation of the Earth node or the camera node.You would need to animate both the camera's position and its orientation. The position animation is straightforward using
SCNAction.For the orientation, you should smoothly transition the
SCNLookAtConstraintto focus on the target.The camera's new position is computed to be a fixed distance from the target, ensuring the target is centered.
The
SCNLookAtConstraintis still used for orientation, but now within an animation transaction to smoothly transition the view.The animation durations are set to 1.5 seconds, but you can adjust this based on your preference for how quick the transition should be.