围绕对象旋转和移动相机在 Swift SceneKit 中不起作用

问题描述 投票:0回答:1

我有一个用 swift 和 SceneKit 构建的基本 3d 交互式地球仪。当视图启动时,镜头指向非洲。我想旋转并移动相机以指向美国俄勒冈州。我有俄勒冈州位置的正确 SCNVector3,但我的函数错误地移动了相机。如何计算旋转以准确地将相机移动到任何 SCNVector3 位置?

我下面的计算是错误的。我假设您必须考虑相机的当前位置并使用它来计算到新位置的旋转和移动。

    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)
    }
ios swift scenekit scnnode
1个回答
0
投票

您需要调整相机的位置和方向。您当前的方法似乎可以正确计算新位置,但似乎无法正确处理相机的旋转。

  • 使用球坐标找到新的相机位置。
  • 将相机指向新的目标位置(俄勒冈州)。

您的

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)
}

该代码首先像您一样计算相机的新位置,但是随后,它使用

SCNLookAtConstraint
,而不是手动旋转相机。该约束会自动调整相机的方向,以始终看着目标节点(在您的例子中,是地球节点)。
并且在应用约束之前更新相机的位置,以确保它指向正确的位置。

假设您的

earthNode
正确位于地球模型的中心。如果
earthNode
不在中心,您可能需要在地球中心创建一个单独的节点并将其用于
SCNLookAtConstraint

© www.soinside.com 2019 - 2024. All rights reserved.