【问题标题】:SCNCamera moving camera's pivotSCNCamera 移动相机的枢轴
【发布时间】:2016-12-14 19:33:21
【问题描述】:

我需要关注某个节点,例如金字塔。然后将距离应用于相机,然后根据用户点击移动相机。我的做法是这样的:

import SceneKit

class GameViewController: UIViewController {
let scene = SCNScene()
override func viewDidLoad() {
    super.viewDidLoad()
    let camera = SCNCamera()
    camera.usesOrthographicProjection = true
    camera.orthographicScale = 4
    camera.zNear = 1
    camera.zFar = 100
    let cameraNode = SCNNode()
    cameraNode.position = SCNVector3(x: 0, y: 0, z: 6)
    cameraNode.camera = camera
    let cameraOrbit = SCNNode()
    cameraOrbit.name = "orbit"
    cameraOrbit.addChildNode(cameraNode)
    scene.rootNode.addChildNode(cameraOrbit)

    let Py = SCNPyramid(width: 2, height: 3, length: 2)
    Py.firstMaterial?.diffuse.contents = UIColor.purple()
    let P = SCNNode(geometry: Py)
    P.position = SCNVector3(x:0,y:0,z:2) //see the note
    scene.rootNode.addChildNode(P)

    /* N O T E :
     the position of the pyramid must not be changed
     as my intention is to rotate the camera
     not the pyramid node
     I repeat, I don't want to rotate the pyramid
     */

    let scnView = self.view as! SCNView
    scnView.scene = scene
    scnView.allowsCameraControl = false
    scnView.backgroundColor = UIColor.black()

    // user rotates the camera by tapping
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
    scnView.addGestureRecognizer(tapGesture)
}


//the function which does camera rotation :
func handleTap(_ gestureRecognize: UIGestureRecognizer) {
    //I guess the solution is around here
    //like modify the cameraOrbit.position ?
    //or cameraNode.position ?
    //tried both but doesn't work
    //or I used them wrong
    let cameraOrbit = scene.rootNode.childNode(withName: "orbit", recursively: true)!
    SCNTransaction.begin()
    SCNTransaction.animationDuration = 2
    cameraOrbit.eulerAngles.z += Float(M_PI_2) //see below
    SCNTransaction.commit()
    /*
     I realise that by performing rotation on the camera
     (the camera position is unchanged) works for z rotation,
     but this is not what I want. What I want is a solution,
     which also works for eulerAngles.x and eulerAngles.y.

     I used eulerAngles.z as example since it's easier to observe.

     I guess the true solution involves moving the camera
     with specific trajectory, not only rotation of "anchored" camera.
     */
     }

//...
}

结果是:

我想要实现的是相对于其中心进行旋转:

我的问题是,如何调整轴心,以便实现相对于金字塔中心的旋转?

注意:我不想旋转金字塔。

【问题讨论】:

    标签: ios swift macos scenekit


    【解决方案1】:

    我找到了解决方案,但我无法解释原因。如果你能解释,请评论。

    必须将相机轨道位置设置为与对象的位置(在本例中为金字塔)相匹配。所以

    cameraOrbit.position = P.position
    

    那么神秘的解决方案来了,将 cameraOrbit.position.y 添加一半的 pi :

    cameraOrbit.position.y += Float(M_PI_2)
    //therefore we have the final cameraOrbit.position as (0, pi/2, 2)
    

    经过测试,适用于所有 cameraOrbit.eulerAngles。 但我不知道它为什么起作用。如果 pi/2 来自某个投影,那么为什么它只隐藏在 y 上?我的意思是,当我执行任何 cameraOrbit.eulerAngles 时,我不需要将此 pi/2 分配给 x 或 z。

    这是完整的代码

    import SceneKit
    
    class GameViewController: UIViewController {
    let scene = SCNScene()
    override func viewDidLoad() {
        super.viewDidLoad()
        let camera = SCNCamera()
        camera.usesOrthographicProjection = true
        camera.orthographicScale = 4
        camera.zNear = 1
        camera.zFar = 100
        let cameraNode = SCNNode()
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 6)
        cameraNode.camera = camera
        let cameraOrbit = SCNNode()
        cameraOrbit.name = "orbit"
        cameraOrbit.addChildNode(cameraNode)
        scene.rootNode.addChildNode(cameraOrbit)
    
        let Py = SCNPyramid(width: 2, height: 3, length: 2)
        Py.firstMaterial?.diffuse.contents = UIColor.purple()
        let P = SCNNode(geometry: Py)
        P.position = SCNVector3(x:0,y:0,z:2)
        scene.rootNode.addChildNode(P)
    
        // S O L U T I O N :
        cameraOrbit.position = P.position
        cameraOrbit.position.y += Float(M_PI_2)
        //therefore we have the final cameraOrbit.position as (0, pi/2, 2)
    
        let scnView = self.view as! SCNView
        scnView.scene = scene
        scnView.allowsCameraControl = false
        scnView.backgroundColor = UIColor.black()
    
        // user rotates the camera by tapping
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
        scnView.addGestureRecognizer(tapGesture)
    }
    
    //the function which does camera rotation :
    func handleTap(_ gestureRecognize: UIGestureRecognizer) {
        //I was wrong, the solution is not here
        let cameraOrbit = scene.rootNode.childNode(withName: "orbit", recursively: true)!
        SCNTransaction.begin()
        SCNTransaction.animationDuration = 2
        cameraOrbit.eulerAngles.z += Float(M_PI_2) //works also for x and y
        SCNTransaction.commit()
    
         }
    
    ...
    }
    

    【讨论】:

      猜你喜欢
      • 2018-08-03
      • 2015-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多