您需要调整相机的位置和方向.您当前的方法似乎正确地计算了新位置,但似乎没有正确处理相机的旋转.
- 使用球面坐标查找新的相机位置.
- 将相机指向新的目标位置(俄勒冈州).
你的centerCameraOnDot
函数的修改版本是:
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 = sin(targetTheta) * cos(targetPhi)
let newY = cos(targetTheta)
let newZ = sin(targetTheta) * sin(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)
// Update the camera's position
cameraNode.position = newCameraPosition
// Orient the camera to look at the target position (Oregon)
let lookAtConstraint = SCNLookAtConstraint(target: earthNode)
lookAtConstraint.isGimbalLockEnabled = true
cameraNode.constraints = [lookAtConstraint]
// Optionally, add animation for smooth transition
cameraNode.runAction(moveAction)
}
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.
这是假设您的earthNode
正确定位在地球模型的中心.如果earthNode
不在中心,则可能需要在地球的中心创建一个单独的 node ,并将其用于SCNLookAtConstraint
.
当在俄勒冈州try 这种方法时,它在一定程度上是有效的,但在过渡之后,俄勒冈州处于地球的右边.这也不会为过渡设置动画.例如,当我try 韩国的位置时,这只是将地球稍微向上旋转了一点,但不起作用.
SCNLookAtConstraint
应该使摄像机直接看到目标,但如果目标不在摄像机视图的中心,这可能是由于地球 node 或摄像机 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 SCNLookAtConstraint
to focus on the target.
func centerCameraOnDot(dotPosition: SCNVector3) {
let fixedDistance: Float = 6.0
let newCameraPosition = dotPosition.normalized().scaled(to: fixedDistance)
// Position animation
let moveAction = SCNAction.move(to: newCameraPosition, duration: 1.5)
// Set up lookAt constraint for orientation
let constraint = SCNLookAtConstraint(target: earthNode)
constraint.isGimbalLockEnabled = true
// Animate the transition
SCNTransaction.begin()
SCNTransaction.animationDuration = 1.5
cameraNode.constraints = [constraint]
cameraNode.runAction(moveAction)
SCNTransaction.commit()
}
The camera's new position is computed to be a fixed distance from the target, ensuring the target is centered.
The SCNLookAtConstraint
is 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.